如何获取JavaScript实例的字段与Getter的名称及值?
如何遍历对象的属性包括Getter(获取名称和值)
嘿,这个问题我之前也踩过坑!Object.entries、Object.keys和Object.values这些方法默认只会处理对象自身可枚举的数据属性,如果Getter是定义在原型链上,或者被设置为不可枚举,就会被跳过。不过有几个可靠的方法能帮你拿到所有Getter的名称和对应的值:
方法一:获取自身所有属性(包括不可枚举和Getter)
用Object.getOwnPropertyDescriptors()可以获取对象自身所有属性的描述符,不管是数据属性还是访问器属性(Getter/Setter)。然后你可以遍历这些描述符,判断是否是Getter,再获取对应的值:
const myInstance = { // 可枚举的自身Getter get foo() { return 'bar'; }, // 不可枚举的自身Getter get hiddenFoo() { return 'hidden bar'; }, // 普通数据属性 baz: 'qux' }; // 给hiddenFoo设置为不可枚举 Object.defineProperty(myInstance, 'hiddenFoo', { enumerable: false }); // 获取所有自身属性的描述符 const allDescriptors = Object.getOwnPropertyDescriptors(myInstance); // 遍历处理 for (const [key, descriptor] of Object.entries(allDescriptors)) { let value; if (descriptor.get) { // 是Getter,直接从实例上获取计算后的值 value = myInstance[key]; console.log(`Getter ${key}: ${value}`); } else { // 普通数据属性,直接取value value = descriptor.value; console.log(`Data property ${key}: ${value}`); } }
执行这段代码会输出:
Getter foo: bar
Getter hiddenFoo: hidden bar
Data property baz: qux
方法二:遍历包括原型链的所有属性
如果你的Getter定义在对象的原型链上(比如类的原型方法),上面的方法就拿不到了。这时候可以用for...in循环遍历所有可枚举属性(包括原型链上的),再配合Object.getOwnPropertyDescriptor来判断是否是Getter:
// 定义一个带有原型Getter的类 class MyClass { constructor() { this.baz = 'qux'; } get foo() { return 'prototype bar'; } } const myInstance = new MyClass(); // 遍历所有可枚举属性(包括原型链) for (const key in myInstance) { // 先从实例本身找属性描述符,找不到就去原型链找 let descriptor = Object.getOwnPropertyDescriptor(myInstance, key); if (!descriptor) { descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(myInstance), key); } if (descriptor.get) { console.log(`Prototype Getter ${key}: ${myInstance[key]}`); } else { console.log(`Data property ${key}: ${myInstance[key]}`); } }
这段代码的输出会是:
Data property baz: qux
Prototype Getter foo: prototype bar
为什么之前的方法不行?
再补充一下你遇到问题的核心原因:
Object.keys/entries/values只会返回对象自身可枚举的属性,原型链上的或者不可枚举的Getter都会被忽略。- Getter属于「访问器属性」,它没有
value属性,而是通过get函数计算值,但如果它是自身可枚举的,Object.values和entries会自动调用get函数获取值返回——如果你没拿到,大概率是Getter在原型链上或者被设为不可枚举了。
内容的提问来源于stack exchange,提问作者Nasgar
相关产品推荐
相关产品推荐

