Javascript Automatic Getter/setters (john Resig Book)
Solution 1:
I think it's best not to use the new
keyword at all when working in JavaScript.
This is because if you then instantiate the object without using the new keyword (ex: var user = User()
) by mistake, *very bad things will happen...*reason being that in the function (if instantiated without the new
keyword), the this
will refer to the global object, ie the window
...
So therefore, I suggest a better way on how to use class-like objects.
Consider the following example :
var user = function (props) {
var pObject = {};
for (p in props) {
(function (pc) {
pObject['set' + pc] = function (v) {
props[pc] = v;
return pObject;
}
pObject['get' + pc] = function () {
return props[pc];
}
})(p);
}
return pObject;
}
In the above example, I am creating a new object inside of the function, and then attaching getters and setters to this newly created object.
Finally, I am returning this newly created object. Note that the the this
keyword is not used anywhere
Then, to 'instantiate' a user
, I would do the following:
var john = user({name : 'Andreas', age : 21});
john.getname(); //returns 'Andreas'
john.setage(19).getage(); //returns 19
The best way to avoid falling into pitfalls is by not creating them in the first place...In the above example, I am avoiding the new
keyword pitfall (as i said, not using the new
keyword when it's supposed to be used will cause bad things to happen) by not using new
at all.
Solution 2:
EDIT: now, adapting Jason's answer, it works:
We need to make a closure for the values. Here's one way:
functionbindAccessors(o, property, value) {
var _value = value;
o["get" + property] = function() {
return _value;
};
o["set" + property] = function(v) {
_value = v;
};
}
Then the User constructor looks like this:
function User( properties ) {
for (var i in properties ) {
bindAccessors(this, i, properties[i]);
}
}
Solution 3:
you probably want something like this, which is more readable: (closures are easy to learn once you get some practice)
functionUser( properties ) {
// helper function to create closures based on passed-in arguments:var bindGetterSetter = function(obj,p,properties)
{
obj["get"+p]=function() { return properties[p]; }
obj["set"+p]=function(val) { properties[p]=val; returnthis; }
};
for (var p in properties)
bindGetterSetter(this, p, properties);
}
I also added "return this;" so you can do:
u=newUser({a: 1, b:77, c:48});
u.seta(3).setb(20).setc(400)
Solution 4:
I started this post with the sole purpose of learning why that things happened, and I finally did. So in case there's someone else interested in the "whys" here they are:
Why does 'this' changes inside the anonymous function?
A new function, even if it is an anonymous, declared inside an object or another function ALWAYS CHANGES THE SCOPE, in this case returning to the global scope (window)
Answer : all stated in the post, I think the clearer is executing the anonymous function with .call(this)
Why getname() always returns the age?
While the anonymous function gets executed right away, the getters/setters get executed for the first time when they are called. In that moment, the value of i will always be the last because it has already iterated for all the properties... and will always return properties[i] which is the last value, in this case the age.
Solution: save the i value in a variable like this
for ( i in properties ) { (function(){
var j = i
//from now on use properties[j]
That's basically it, if I'm wrong in anything I said please correct me, since I'm trying to learn this...
Thanks again.
Solution 5:
As written in the OP, this
in the loop is not referring to the User object as it should be. If you capture that variable outside the loop, you can make it work:
functionUser( properties ) {
// Iterate through the properties of the object, and make sure// that it's properly scoped (as discussed previously)var me = this;
for ( i in properties ) { (function(){
// Create a new getter for the property
me[ "get" + i ] = function() {
return properties[i];
};
// Create a new setter for the property
me[ "set" + i ] = function(val) {
properties[i] = val;
};
// etc
Post a Comment for "Javascript Automatic Getter/setters (john Resig Book)"