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.
About the property (and attribute) descriptors mentioned at the end of the answer, it has a more in-depth detail on What and how Javascript property descriptors and attributes work?. :)
– Luiz Felipe