Если объект является экземпляром класса и методы лежат в прототипе, где их увидим: в for-in или Object.keys
Что проверяют
Знаете ли вы разницу между собственными и унаследованными свойствами и понимаете ли, что такое перечисляемость. Ловушка в слове «класс»: следом часто просят показать, как всё-таки получить список методов экземпляра.
Как отвечать
Правильный ответ: при синтаксисе class методов не будет ни там, ни там. Разберите по шагам:
Object.keys: возвращает только собственные перечисляемые строковые ключи. Методы лежат наFoo.prototype, а не на экземпляре, поэтому сюда не попадают;for...in: обходит перечисляемые свойства по всей цепочке прототипов. Но методы, объявленные в телеclass, создаются сenumerable: false, поэтому иfor...inих пропускает. Так же неперечисляемы геттеры и сеттеры класса;- старый стиль: если метод добавлен вручную,
Foo.prototype.bar = function () {}, он перечисляемый, иfor...inего покажет, аObject.keysнет. Именно этот случай обычно имеют в виду ответы в духе «в for-in увидим»; - поля класса:
count = 0и стрелочныеhandle = () => {}становятся собственными свойствами экземпляра, их покажут оба способа; - как достать методы:
Object.getOwnPropertyNames(Object.getPrototypeOf(obj))вернёт имена вместе сconstructor.Reflect.ownKeysдобавит символы,Object.getOwnPropertyDescriptorsпокажет флаги.
Будет плюсом, если упомянете транспиляцию: при сборке в ES5 (TypeScript с target: "ES5", Babel в loose-режиме) методы класса превращаются в присваивания в прототип и становятся перечисляемыми. Один и тот же код может вести себя по-разному в зависимости от сборки.
Где спотыкаются
Отвечают «в for...in увидим, в Object.keys нет», не уточняя, как объявлен метод. Для современного class это неверно.
Путают перечисляемость с принадлежностью. Object.keys отсекает унаследованное, а enumerable: false скрывает свойство даже от for...in.
Используют for...in для обхода данных без проверки Object.hasOwn(obj, key). Любое перечисляемое свойство, добавленное в прототип сторонней библиотекой, попадёт в цикл.