What is the __defineSetter__ and __defineGetter__property for?

Asked

Viewed 269 times

3

Every time I open the Chrome Console, I keep an eye on the properties autocomplete, to see if something new comes up, something I haven’t learned yet. And it struck me to see that objects have the property called __defineSetter__ and __defineGetter__.

I noticed that this property exists in the object window, as well as in literal objects that we create.

I’d like to know exactly how this works.

These properties affect the way values are defined in an object What is the purpose of these values?

I would like to know details about browser compatibility (I’m asking this question in 2018) and if it has anything to do with Object.defineProperty

2 answers

4


So much Object.prototype.__defineSetter__ how much Object.prototype.__defineGetter__ are obsolete methods (and also were not standardized), in their places can use the method:

Their use, both of obsolete methods and of the new/standardized API, is to "detect/execute" when it occurs of setting a value to an object property (set) and when trying to get the value of a property (get).

But of course it’s not just taking a value or setar one, actually at this point you as a programmer will decide whether you will actually set something or whether you will return something, similar to magic methods __set and __get of PHP.


Detecting when you set a value to an object

If you want a function to be triggered when set a value then do it in the old syntax:

var o = {};

o.__defineSetter__('foo', function(val) {
    console.log("foo:", val);
});

o.__defineSetter__('bar', function(val) {
    console.log("bar:", val);
});

document.getElementById("to-foo").onclick = function () {
    o.foo = new Date().toString();
};

document.getElementById("to-bar").onclick = function () {
    o.bar = new Date().toString();
};

document.getElementById("get-foo").onclick = function () {
    console.log(o.set);
};

document.getElementById("get-bar").onclick = function () {
    console.log(o.bar);
};
<button id="to-foo">Setar valor para o.foo</button>
<button id="to-bar">Setar valor para o.bar</button><br>
<button id="get-foo">Exibir valor de o.foo</button>
<button id="get-bar">Exibir valor de o.bar</button>

Standardized syntax:

var o = {};

Object.defineProperty(o, 'foo', {
    set: function(val) {
         console.log("foo:", val);
    }
});

Object.defineProperty(o, 'bar', {
    set: function(val) {
         console.log("bar:", val);
    }
});

document.getElementById("to-foo").onclick = function () {
    o.foo = new Date().toString();
};

document.getElementById("to-bar").onclick = function () {
    o.bar = new Date().toString();
};

document.getElementById("get-foo").onclick = function () {
    console.log(o.set);
};

document.getElementById("get-bar").onclick = function () {
    console.log(o.bar);
};
<button id="to-foo">Setar valor para o.foo</button>
<button id="to-bar">Setar valor para o.bar</button><br>
<button id="get-foo">Exibir valor de o.foo</button>
<button id="get-bar">Exibir valor de o.bar</button>

Note that you did not set any value on the buttons to display the console.log just displays undefined, this means that we only intercept the execution/action of setar, but within the function defined nothing is done, so it is at this point that you decide whether something will occur and how it should occur.


Detecting when trying to pick up a value from an object

If you want to have a custom value according to your business/behavior needs then you would do this with old syntax:

var o = {};

o.__defineGetter__('foo', function(val) {
    return +new Date;
});

o.__defineGetter__('bar', function() {
    return +new Date;
});

document.getElementById("get-foo").onclick = function () {
    console.log("valor de foo:", o.foo);
};

document.getElementById("get-bar").onclick = function () {
    console.log("valor de bar:", o.bar);
};
<button id="get-foo">Pegar valor de o.foo</button>
<button id="get-bar">Pegar valor de o.bar</button>

Standardized syntax:

var o = {};

Object.defineProperty(o, 'foo', {
    get: function () {
       return +new Date;
    }
});

Object.defineProperty(o, 'bar', {
    get: function () {
       return +new Date;
    }
});

document.getElementById("get-foo").onclick = function () {
    console.log("valor de foo:", o.foo);
};

document.getElementById("get-bar").onclick = function () {
    console.log("valor de bar:", o.bar);
};
<button id="get-foo">Pegar valor de o.foo</button>
<button id="get-bar">Pegar valor de o.bar</button>


Using Object.defineProperty with get and set

One detail is that in the standard syntax you don’t need to do:

var o = {};

Object.defineProperty(o, 'bar', {
    get: function () {
       /* retorna valor */
    }
});

Object.defineProperty(o, 'foo', {
    set: function (val) {
       /* seta valor */
    }
});

o.foo = 'test'; //Executa set:
console.log(o.foo); //Executa get:

You can do so for the o.foo:

var o = {};

Object.defineProperty(o, 'foo', {
    get: function () {
       /* retorna valor */
    },
    set: function (val) {
       /* seta valor */
    }
});

o.foo = 'test'; //Executa set:
console.log(o.foo); //Executa get:

Operators set and get

Alternatively to Object.defineProperty you can use the operators:

var o = {
    set foo(val) {
       console.log("Seta valor para o.foo:", val);
    },
    set bar(val) {
       console.log("Seta valor para o.bar:", val);
    },
    set baz(val) {
       console.log("Seta valor para o.baz:", val);
    },
    get foo() {
       return +new Date;
    },
    get bar() {
       return +new Date;
    },
    get baz() {
       return +new Date;
    }
};

o.foo = 100;
o.bar = 220;
o.baz = 333;

console.log("Pega o valor de o.foo:", o.foo);
console.log("Pega o valor de o.bar:", o.bar);
console.log("Pega o valor de o.baz:", o.baz);


Object.defineProperty vs get/set

Although some places claim that they are identical in their goals, the use of Object.defineProperty in the third parameter (where we define the get and set) has some specific settings:

  • configurable
  • enumerable
  • value (optional)
  • writable (optional)

I will be editing this part soon with details, I never really used these settings to understand well the functioning.

0

They serve to define a method that will be called when something is trying to assign a new value to the current object, or when something tries to read the value of the current object.

Example.

var obj = "";
obj.__defineSetter__('value', function(val) { alert('x'); });

In the above case, if any method tries to change the value of the obj variable, an alert will be issued with the text "x".

The same thing for the defineGetter, but for reading the value.

  • (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype) here is the definition and examples.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.