Define getter using defineProperty

Tags:



In our application we compress our JavaScript classes using UglifyJS which doesn’t support being able to compress syntax like onBlur = (event) => {} as it returns Unexpected token: operator (=).

To solve this problem we have used the following function to define them:

function _defineProperty(obj, key, value) {
    if (key in obj) {
        Object.defineProperty(obj, key, {
            value: value,
            enumerable: true,
            configurable: true,
            writable: true
        });
    } else {
        obj[key] = value;
    }
    return obj;
}

And then we use it inside our constructor like so:

class OurClass {
    constructor(...args) {
        super(...args);
            _defineProperty(this, "onBlur", event => {
     
            });
    }
}

Which works great! however it doesn’t work for defining getters:

static get values() {
    return { index: Number }
}

Like so:

_defineProperty(this, 'values', () => {
    return { index: Number };
});

The getter is never defined and isn’t accessible in the rest of the class in the same way that we were able to define the other methods…

How can we define the getter using this same function with defineProperty?

Answer

Object.defineProperty accepts two different formats for its third argument:

  • data descriptor, which you currently use
  • accessor descriptor, which allows for defining a getter/setter

So, for instance, you could extend your own _defineProperty function with an optional argument to indicate that a getter/setter is intended:

function _defineProperty(obj, key, value, accessor) {
    if (accessor == "getter") {
        Object.defineProperty(obj, key, {
            get: value,
            enumerable: true,
            configurable: true,
        });
    } else if (key in obj) {
        Object.defineProperty(obj, key, {
            value: value,
            enumerable: true,
            configurable: true,
            writable: true
        });
    } else {
        obj[key] = value;
    }
    return obj;
}

// simple demo
class MyClass {
    constructor() {
        _defineProperty(this, "num", () => 3, "getter");
    }
}

console.log(new MyClass().num);

If you want it as a static method, then define it on the class (i.e. on the constructor):

function _defineProperty(obj, key, value, accessor) {
    if (accessor == "getter") {
        Object.defineProperty(obj, key, {
            get: value,
            enumerable: true,
            configurable: true,
        });
    } else if (key in obj) {
        Object.defineProperty(obj, key, {
            value: value,
            enumerable: true,
            configurable: true,
            writable: true
        });
    } else {
        obj[key] = value;
    }
    return obj;
}

// simple demo
class MyClass {}
_defineProperty(MyClass, "num", () => 3, "getter");

console.log(MyClass.num);


Source: stackoverflow