Learn JavaScript

propertyIsEnumerable() - метод для проверки перечисляемого свойства объекта в JavaScript

propertyIsEnumerable() проверяет, является ли свойство объекта перечисляемым.

Важно понимать сразу: метод возвращает true только для собственных перечисляемых свойств объекта.

Синтаксис

obj.propertyIsEnumerable(propertyName)

propertyName - имя свойства, которое нужно проверить.

Что делает propertyIsEnumerable()

Если свойство есть у самого объекта и оно перечисляемое, метод вернёт true.

const user = {
  name: "Anna",
};

console.log(user.propertyIsEnumerable("name")); // true
console.log(user.propertyIsEnumerable("age"));  // false

Что возвращает propertyIsEnumerable()

propertyIsEnumerable() всегда возвращает булево значение:

  • true, если свойство собственное и перечисляемое
  • false, если это не так
const user = { name: "Anna" };

console.log(user.propertyIsEnumerable("name")); // true
console.log(user.propertyIsEnumerable("role")); // false

Почему важно слово “перечисляемое”

Не все свойства объекта участвуют в переборе через for...in, Object.keys() и похожие методы.

Если свойство неперечисляемое, propertyIsEnumerable() вернёт false.

const user = { name: "Anna" };

Object.defineProperty(user, "secret", {
  value: "123",
  enumerable: false,
});

console.log(user.propertyIsEnumerable("name"));   // true
console.log(user.propertyIsEnumerable("secret")); // false

Только собственные свойства

Свойства из прототипа сюда не засчитываются.

const base = { role: "user" };
const person = Object.create(base);

person.name = "Anna";

console.log(person.propertyIsEnumerable("name")); // true
console.log(person.propertyIsEnumerable("role")); // false

Хотя person.role доступно, оно унаследовано, поэтому метод возвращает false.

propertyIsEnumerable() и hasOwnProperty()

Эти методы похожи, но проверяют разное.

const user = { name: "Anna" };

Object.defineProperty(user, "secret", {
  value: "123",
  enumerable: false,
});

console.log(user.hasOwnProperty("secret"));       // true
console.log(user.propertyIsEnumerable("secret")); // false

hasOwnProperty() проверяет только то, что свойство собственное.

propertyIsEnumerable() дополнительно проверяет, является ли оно перечисляемым.

propertyIsEnumerable() и Object.keys()

Object.keys() возвращает все собственные перечисляемые строковые ключи объекта.

propertyIsEnumerable() проверяет одно конкретное свойство.

const user = { name: "Anna", age: 25 };

console.log(Object.keys(user)); // ["name", "age"]
console.log(user.propertyIsEnumerable("name")); // true

Если Object.keys() включил бы ключ в результат, то для такого ключа propertyIsEnumerable() обычно тоже даст true.

Если значение равно undefined

Метод проверяет не значение свойства, а его статус.

const user = {
  age: undefined,
};

console.log(user.propertyIsEnumerable("age")); // true
console.log(user.age); // undefined

То есть undefined не мешает свойству быть перечисляемым.

Массивы и propertyIsEnumerable()

Массив тоже является объектом, поэтому метод работает и с ним.

const arr = ["a", "b"];

console.log(arr.propertyIsEnumerable("0")); // true
console.log(arr.propertyIsEnumerable("1")); // true

Интересный нюанс: length у массива не перечисляется.

const arr = ["a", "b"];

console.log(arr.propertyIsEnumerable("length")); // false

Символьные ключи

Метод умеет работать и с ключами-символами.

const id = Symbol("id");
const user = {
  [id]: 1,
};

console.log(user.propertyIsEnumerable(id)); // true

Это полезно знать, потому что, например, Object.keys() символьные ключи не возвращает.

Object.create(null)

У объекта без прототипа метода propertyIsEnumerable() нет.

const dict = Object.create(null);
dict.name = "Anna";

// dict.propertyIsEnumerable("name"); // Ошибка

В таком случае можно вызвать метод так:

console.log(Object.prototype.propertyIsEnumerable.call(dict, "name")); // true

Когда это полезно

propertyIsEnumerable() удобно использовать, когда:

  • нужно понять, попадёт ли свойство в перечисление
  • нужно отличить неперечисляемое свойство от обычного
  • нужно точнее проверить объект, чем через hasOwnProperty()

Пример:

const settings = {
  theme: "dark",
};

console.log(settings.propertyIsEnumerable("theme")); // true

propertyIsEnumerable() не меняет объект

Метод только проверяет свойство и не изменяет сам объект.

const user = { name: "Anna" };
const result = user.propertyIsEnumerable("name");

console.log(user);   // { name: "Anna" }
console.log(result); // true

Частые ошибки

Путать propertyIsEnumerable() и hasOwnProperty()

const user = { name: "Anna" };

Object.defineProperty(user, "secret", {
  value: "123",
  enumerable: false,
});

console.log(user.hasOwnProperty("secret"));       // true
console.log(user.propertyIsEnumerable("secret")); // false

Свойство есть, но оно неперечисляемое.

Думать, что унаследованное свойство может дать true

const base = { role: "user" };
const person = Object.create(base);

console.log(person.propertyIsEnumerable("role")); // false

Метод проверяет только собственные свойства.

Вызывать метод у Object.create(null)

const dict = Object.create(null);

// dict.propertyIsEnumerable("name"); // Ошибка

У такого объекта нет методов из Object.prototype.

Быстрая памятка

  • propertyIsEnumerable() проверяет, является ли свойство собственным и перечисляемым
  • унаследованные свойства дадут false
  • неперечисляемые свойства тоже дадут false
  • метод возвращает true или false
  • для объектов без прототипа используют Object.prototype.propertyIsEnumerable.call(...)

Коротко

propertyIsEnumerable() - это способ проверить, участвует ли свойство объекта в перечислении. Главное, что стоит запомнить: метод возвращает true только для собственных перечисляемых свойств и полезен, когда нужно точнее понимать поведение объекта при переборе.