我最近在ES6上工作,我非常喜欢。
问题在于我遇到了一个非常糟糕的问题:我无法找到一种方法来枚举类的所有属性描述符。
class A {
get property(){
return "the 'a' value";
}
}
const a = new A();
const b = {
get property() {
return "the 'b' value";
}
};
const objectKeys = (obj) => {
return Object.keys(obj).join(', ');
};
const objectPropertyNames = (obj) => {
return Object.getOwnPropertyNames(obj).join(', ');;
};
const objectForIn = (obj) => {
const result = [];
for(const prop in obj){
result.push(prop);
}
return result.join(', ');;
}
console.log(objectKeys(a)); // Output empty string
console.log(objectKeys(b)); // Output 'property'
console.log(objectPropertyNames(a)); // Output empty string
console.log(objectPropertyNames(b)); // Output 'property'
console.log(objectForIn(a)); // Output empty string
console.log(objectForIn(b)); // Output 'property'
console.log(a.hasOwnProperty("property")); // Output false
console.log(b.hasOwnProperty("property")); // Output true
console.log(Object.getOwnPropertyDescriptor(a, "property")); // Output undefined
console.log(Object.getOwnPropertyDescriptor(b, "property")); // Output a valid descriptor
答案 0 :(得分:2)
关键是a
没有任何属性。它确实从property
继承了A.prototype
getter:
console.log(objectPropertyNames(Object.getPrototypeOf(a)));
console.log(objectPropertyNames(A.prototype));
如果您想要所有已继承和不可枚举的属性,则必须手动walk the prototype chain。
答案 1 :(得分:0)
经过一天的调查后,我最终得出了同样的结论
重点是a没有任何属性。它确实从A.prototype继承了属性getter:
console.log(objectPropertyNames(Object.getPrototypeOf(a)));
console.log(objectPropertyNames(A.prototype));
如果您想要所有继承和非可枚举的属性,则必须手动遍历原型链。
作为一个好的解决方法,我为我的AbstractEntity
添加了一个静态属性来完成这项工作(仅考虑使用类getter / setter)
class AbstractEntity {
static get keys() {
const keys = [];
const entries = Object.getOwnPropertyNames(this.prototype);
for (const entry of entries) {
const descriptor = Object.getOwnPropertyDescriptor(this.prototype, entry);
if (descriptor.hasOwnProperty("get")) {
keys.push(entry);
}
}
return keys;
}
}
const _property = new WeakMap();
class FakeEntity extends AbstractEntity {
get readOnlyProperty() {
return true;
}
get property() {
return _property.get(this);
}
set property(value) {
_property.set(this, value);
}
method() {}
static staticMethod() {}
static get staticProperty() {}
}
console.log(FakeEntity.key); // output ["readOnlyProperty", "property"]