Javascript automatic getter/setters (John Resig Book)
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.
EDIT: now, adapting Jason's answer, it works:
We need to make a closure for the values. Here's one way:
function bindAccessors(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]); }}
you probably want something like this, which is more readable: (closures are easy to learn once you get some practice)
function User( 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; return this; } }; for (var p in properties) bindGetterSetter(this, p, properties);}
I also added "return this;" so you can do:
u=new User({a: 1, b:77, c:48});u.seta(3).setb(20).setc(400)