为何带get访问器的类属性无法被Object.keys等方法获取?
问题解答
核心原因:类的getter默认不可枚举
你定义的bar是类原型上的getter属性,而JavaScript类中所有定义在原型上的成员(包括方法、getter/setter),默认的**enumerable(可枚举性)**都是false。
Object.keys()、Object.entries()、Object.values()这类方法只会遍历对象自有且可枚举的属性;for...in循环则会遍历对象自身及原型链上可枚举的属性。因为bar的enumerable为false,所以自然不会被这些方法/循环捕获到。
你可以通过Object.getOwnPropertyDescriptor验证这一点:
console.log(Object.getOwnPropertyDescriptor(Foo.prototype, 'bar')); // 输出:{ get: [Function: get bar], set: undefined, enumerable: false, configurable: true }
如何让getter可被遍历?
有两种常见方式可以让bar变成可枚举属性:
1. 将getter定义为实例的自有可枚举属性
在类的构造函数中,用Object.defineProperty把getter绑定到实例上,并设置enumerable: true:
class Foo { constructor() { Object.defineProperty(this, 'bar', { get: () => 'barval', enumerable: true, configurable: true }); } }
2. 修改原型上getter的可枚举性
直接修改类原型上bar属性的enumerable配置:
class Foo { get bar() { return 'barval'; } } // 修改原型属性的可枚举性 Object.defineProperty(Foo.prototype, 'bar', { enumerable: true });
或者用ES2022+的类静态块来完成配置,写法更优雅:
class Foo { static { Object.defineProperty(this.prototype, 'bar', { get: () => 'barval', enumerable: true }); } }
验证效果
修改后再运行测试代码,就能得到预期结果:
const foo = new Foo(); console.log(foo.bar, // barval Object.keys(foo), // ["bar"] Object.entries(foo), // [["bar", "barval"]] Object.values(foo)); // ["barval"] for (let key in foo) console.log(key, foo[key]); // 输出:bar barval
内容的提问来源于stack exchange,提问作者nicfv
相关产品推荐
相关产品推荐

