How To Enumerate/discover Getters And Setters In Javascript?
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:
- https://2ality.com/2011/06/prototypes-as-classes.html
- https://2ality.com/2012/11/property-assignment-prototype-chain.html
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?"