Skip to content Skip to sidebar Skip to footer

How To Enumerate/discover Getters And Setters In Javascript?

I am trying to discover the getters and setters on an object in typescript. I've tried Object.entries() and Object.keys() and neither of these return getters and setters. How ca

Solution 1:

The reason this doesn't work is that the getter is on the class's prototype, which is on the instance's prototype chain, rather than on the instance itself.

To illustrate:

classA {
  getx() { return1 }
}

aInstance=newA()//A {}

Object.getOwnPropertyDescriptors(aInstance)// {}

Object.getOwnPropertyDescriptors(A.prototype)// { constructor://    { value: [Function:A],
//writable:true,
//enumerable:false,
//configurable:true },
//x://    { get: [Function:getx],
//set:undefined,
//enumerable:false,
//configurable:true } }

Object.getOwnPropertyDescriptors(Object.getPrototypeOf(aInstance))// { constructor://    { value: [Function:A],
//writable:true,
//enumerable:false,
//configurable:true },
//x://    { get: [Function:getx],
//set:undefined,
//enumerable:false,
//configurable:true } }

There a few good blog posts by Axel Rauschmayer on this topic:

Note that if you are trying to enumerate all the properties, accessors, and methods on an object you will need to recursively walk the prototype chain until an object has a null prototype.

Solution 2:

The function Object.getOwnPropertyDescriptors is in the ECMAScript latest draft specification, but is implemented in popular browsers. It returns the property descriptors belonging to an object.

Your use-case is a bit more difficult because the getter is defined on the class, not the object itself. So, you need to walk the prototype chain and build it that way. It's not enough to look at just the object's prototype, because the getter could be inherited from any superclass of the object's class.

Here's a recursive function which does it:

functiongetAllPropertyDescriptors(obj) {
    if (!obj) {
        returnObject.create(null);
    } else {
        const proto = Object.getPrototypeOf(obj);
        return {
            ...getAllPropertyDescriptors(proto),
            ...Object.getOwnPropertyDescriptors(obj)
        };
    }
}

The output for JSON.stringify(getAllPropertyDescriptors(thing)) is below. myGetter is the third property descriptor; the actual output if you don't JSON.stringify it also includes references to the actual functions, so you can see if they have get/set properties.

{"myProperty":{"value":22,"writable":true,"enumerable":true,"configurable":true},"constructor":{"writable":true,"enumerable":false,"configurable":true},"myGetter":{"enumerable":false,"configurable":true},"__defineGetter__":{"writable":true,"enumerable":false,"configurable":true},"__defineSetter__":{"writable":true,"enumerable":false,"configurable":true},"hasOwnProperty":{"writable":true,"enumerable":false,"configurable":true},"__lookupGetter__":{"writable":true,"enumerable":false,"configurable":true},"__lookupSetter__":{"writable":true,"enumerable":false,"configurable":true},"isPrototypeOf":{"writable":true,"enumerable":false,"configurable":true},"propertyIsEnumerable":{"writable":true,"enumerable":false,"configurable":true},"toString":{"writable":true,"enumerable":false,"configurable":true},"valueOf":{"writable":true,"enumerable":false,"configurable":true},"__proto__":{"enumerable":false,"configurable":true},"toLocaleString":{"writable":true,"enumerable":false,"configurable":true}}

You could convert this into an iterative version, but that's probably unnecessary since most prototype chains are short, and the iterative version would need some wrangling to get overrides in the right order.

Solution 3:

You can enumerate the getter name with this function:

functionlistGetters (instance) {
  returnObject.entries(
    Object.getOwnPropertyDescriptors(
      Reflect.getPrototypeOf(instance)
    )
  )
  .filter(e =>typeof e[1].get === 'function' && e[0] !== '__proto__')
  .map(e => e[0]);
}

It will returns an array containing the getters names.

Solution 4:

You can try something like:

var obj = {
  getfoo() {
    returnMath.random() > 0.5 ? 'foo' : 'bar';
  }
};

Object.keys(obj).forEach(key => {
  console.log("Getter:", Object.getOwnPropertyDescriptor(obj, key).get);
  console.log("Setter: ", Object.getOwnPropertyDescriptor(obj, key).set);
})

Hope this works for you.

Post a Comment for "How To Enumerate/discover Getters And Setters In Javascript?"