Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access default getter/setter for JavaScript object

JavaScript getters and setters can be overridden for specific properties using Object.defineProperty. Is there some way to access the default getter/setter (i.e. the function used if the getter/setter has not been overwritten)? In my custom setter I want to have special processing in some cases, but use the default processing in others. I tried:

Object.defineProperty(obj, 'foo',
  'set': function(val) {
    if (useCustom) {
      doCustomProcessing(obj, 'foo', val);
    }
    else {
      obj['foo'] = val;
    }
  }
);

Unfortunately this leads to a stack overflow since obj['foo'] = val; causes the custom setter to be invoked. So I'd like to find a way to set the foo property of obj using the default setter. Is this possible?

like image 392
Matthew Gertner Avatar asked Nov 25 '14 15:11

Matthew Gertner


People also ask

Are there getters and setters in JavaScript?

JavaScript Accessors (Getters and Setters)ECMAScript 5 (ES5 2009) introduced Getter and Setters. Getters and setters allow you to define Object Accessors (Computed Properties).

What does .get do in JavaScript?

The get syntax binds an object property to a function that will be called when that property is looked up.

What is object accessor in JavaScript?

JavaScript object accessors are used to access and update the objects and two keywords used for this function are getter and the other is the setter. JavaScript introduced getters and setters in ES5 in 2009.


2 Answers

As far as I know, a property either has a value (data property), or it has getter/setter (accessor property): it cannot have both. Use a local variable under closure, or another property, as an underlying storage for properties where you have a getter/setter defined.

For example,

(function() {
    var value;
    Object.defineProperty(obj, 'foo', {
      set: function(val) {
        if (useCustom) {
          value = doCustomProcessing(obj, 'foo', val);
        } else {
          value = val;
        }
      },
      get: function() { return value; }
    });
})();
like image 88
Amadan Avatar answered Oct 04 '22 08:10

Amadan


In ES6 you can use a Proxy object:

var myObject = {};

var myProxyObject = new Proxy(myObject, {
  set: function(ob, prop, value) {
    if (prop === 'counter' && value === 10) {
      // Some specialised behaviour
      ob.counter = 0;
    }
    else {
      // Default setter behaviour.
      ob[prop] = value;
    }
    // Return true otherwise you will get a TypeError in strict mode.
    return true;
  }
});

>>> myProxyObject.counter = 5;
>>> console.log(myProxyObject.counter);
5

>>> myProxyObject.counter = 10;
>>> console.log(myProxyObject.counter);
0
like image 36
Andrew Magee Avatar answered Oct 04 '22 09:10

Andrew Magee