0

I'm recently working on ES6 which I really enjoy.

The problem is that I experienced a really bad issue: I can't find a way to enumerate all my properties descriptors of a Class.

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 Answers2

2

The point is that a does not have any own properties. It does inherit the property getter from A.prototype:

console.log(objectPropertyNames(Object.getPrototypeOf(a)));
console.log(objectPropertyNames(A.prototype));

If you want all inherited and non-enumerable properties, you'll have to walk the prototype chain manually.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
0

After spending a day of investigations, I end up at the same conclusion that

The point is that a does not have any own properties. It does inherit the property getter from A.prototype:

console.log(objectPropertyNames(Object.getPrototypeOf(a))); console.log(objectPropertyNames(A.prototype));

If you want all inherited and non-enumerable properties, you'll have to walk the prototype chain manually.

As a good workaround I added a static property to my AbstractEntity in order to do the job (considering only using class 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"]