David David - 1 year ago 91
Javascript Question

Storing an ES6 Javascript class's getter/setter when inheritance is involed

Edit: The reason I am doing the below process is so I can store the reference to the getter/setter in a dictionary. This allows me to have the key of my dictionary be an ID of an HTML element. Thus, if a property is changed in the HTML, I can do something like:

var propData = allMyGetterSetters[e.originalTarget.id];
propData.getSet.set(propData.obj, e.originalTarget.value);

This also allows me to do a loop and update all the HTML, should my logic change it.

I need to store a reference to the getter/setters of a few properties of one of classes. I've managed to do this with the following code:

Object.getOwnPropertyDescriptor(Object.getPrototypeOf(myClassObj.position), "x");

For simplicity, since I have to do this several times, I have the following method:

_makeGetSetObj(object, property){
return {
getSet: Object.getOwnPropertyDescriptor(Object.getPrototypeOf(object), property),
obj: object

And subsequent code would look something like this:

var xPos = this._makeGetSetObj(myClassObj.position, "x");
// ...

All of this works perfectly.

However, I now need to store a reference to a getter/setter of my
object. However, the following does not work

this._makeGetSetObj(myClassObj, "name");

This actually gives me an error that
does not exist on the object. I've managed to figure out that the problem is my inheritance, which looks something like this

|-- BaseClass
|-- MyClass
|-- DerivedClass

The problem seems to be that
is actually an object of type
, which doesn't have the property
on it.

So, if I do this:

this._makeGetSetObj(myClassObj.__proto__, "name");

It works to get the prototype, but when I try to use it as shown above (with my
example), it fails because it seems to still be storing an reference in
as a

If I pull outside of my method, and try things manually, this works:

var name = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(myClassObj.__proto__), "name");

This obviously breaks my method though, as one part requires the
while the other part does not.

So, my question is: Is there a way to keep my current logic, or will I have to create a special method for the places with the described problem?


Answer Source

Hardcoded prototype doesn't smell good. Prototype chains should always be iterated:

let proto = obj;
let descriptor;
do {
  descriptor = Object.getOwnPropertyDescriptor(proto, prop);
} while (!descriptor && proto = Object.getPrototypeOf(proto))

This functionality has been already implemented by Reflect. Instead of parsing descriptors manually, it may be

const getSet = {
  get: () => Reflect.get(obj, prop),
  set: (val) => { Reflect.set(obj, prop, val) }

Or... just

const getSet = {
  get: () => obj[prop],
  set: (val) => { obj[prop] = val }

Because this is what happens when accessors are called directly.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download