Вопрос проверяет понимание особенностей перебора свойств объекта в JavaScript и умение избегать унаследованных свойств прототипа, что важно для корректной работы с данными.
В JavaScript объекты имеют прототипную природу, и при переборе свойств с помощью цикла for...in могут быть захвачены не только собственные свойства объекта, но и перечисляемые свойства, унаследованные из его цепочки прототипов. Это может привести к неожиданному поведению, если вы хотите работать только с данными, непосредственно принадлежащими объекту.
Рассмотрим пример, где у объекта есть собственное свойство и унаследованное от прототипа:
const animal = { eats: true };
const rabbit = { jumps: true, name: 'Bunny' };
Object.setPrototypeOf(rabbit, animal); // rabbit.__proto__ = animal
for (let key in rabbit) {
console.log(key); // Выведет: jumps, name, eats
}Как видно, свойство eats из прототипа также было перечислено.
Классический способ фильтрации — использовать метод hasOwnProperty, который проверяет, принадлежит ли свойство самому объекту, а не его прототипу:
for (let key in rabbit) {
if (rabbit.hasOwnProperty(key)) {
console.log(key); // Выведет: jumps, name
}
}Этот метод надёжен, но требует дополнительной проверки внутри цикла.
Начиная с ES5, появились более удобные методы, которые сразу возвращают только собственные перечисляемые свойства объекта:
Object.keys(obj) — возвращает массив ключей.Object.values(obj) — возвращает массив значений.Object.entries(obj) — возвращает массив пар [ключ, значение].console.log(Object.keys(rabbit)); // ['jumps', 'name']
console.log(Object.values(rabbit)); // [true, 'Bunny']
console.log(Object.entries(rabbit)); // [['jumps', true], ['name', 'Bunny']]Эти методы не включают свойства из прототипа, что делает их предпочтительными для большинства задач итерации.
Object.keys и его аналоги, когда вам нужны только собственные свойства объекта. Это чище и безопаснее.for...in с проверкой hasOwnProperty может пригодиться в редких случаях, когда нужно также анализировать цепочку прототипов, но с фильтрацией.Object.keys не возвращает неперечисляемые свойства (те, у которых флаг enumerable: false). Для получения всех собственных свойств, включая неперечисляемые, можно использовать Object.getOwnPropertyNames(obj).Вывод: Для безопасного перебора только собственных свойств объекта всегда предпочитайте методы Object.keys, Object.values или Object.entries, так как они исключают свойства прототипа по умолчанию и делают код более читаемым и надёжным.