无法枚举类的所有副作用 - 可能的错误?

时间:2016-05-20 10:20:57

标签: javascript properties ecmascript-6 enumerable

我最近在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

2 个答案:

答案 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"]