I’m referring to this article.
I’m basically creating a class with an init function which set an options attribute. see http://jsbin.com/usaboh/1/edit for the working example (enable the console to see the output).
Below the first example works fine, however the second still get the options value of the first “instance”.
Works as expected :
var Person = Class.extend({
options: {value: 2},
init: function(options){
if(options) {
this.options = options;
}
}
});
var p = new Person({value: 5});
console.log(p.options); //{"value": 5} (ok)
var p2 = new Person();
console.log(p2.options); //{"value": 2} (ok)
Doesn’t work as expected :
var Person = Class.extend({
options: {value: 2},
init: function(options){
if(options) {
for (var name in options) {
this.options[name] = options[name];
}
}
}
});
var p = new Person({value: 5});
console.log(p.options); //{"value": 5} (ok)
var p2 = new Person();
console.log(p2.options); //{"value": 5} (why 5 ??? shouldn't be 2 ?)
Why the value of options in the second instance is not {"value": 2} like in the first example ?
That’s because
optionsis a property of the class (on its prototype), not the object.Verify it by adding this to the bottom of your second example:
Explanation:
When using abstraction layers, it is very important to remember the underlying principles, so that you don’t get bitten by the abstractions’ leaks.
Your 1st example:
Let’s re-write your class definition with regular Prototypal inheritance:
johnwill now be a new instance ofPersonand will not have anoptionsproperty:When trying to access the
optionsviajohn.options, you’ll get the{value: 2}from the prototype chain.If however you were to create this new
Personobject by supplying youroptionsto the constructor:michaelwill have anoptionsproperty:Here’s a simple test comparing the two:
Your 2nd example:
Now consider your second example, written in native Prototypal inheritance:
Regardless of whether you pass
optionsinto the constructor, your new object will never have its ownoptionsproperty. All you’re doing is augmenting theoptionson the prototype:If you then go and assign a new object to
john, it won’t affect theoptionson the prototype:Solution:
To get the functionality you want in your second example, you’ll have to follow these steps:
optionsproperty from within the constructor (theinitmethod).Person.prototype.options.optionsargument.Here’s how you might do that:
If you’re using jQuery or underscore, you can use their
extendmethod, which makes all this trivial:Simpler solution:
Depending on your needs, you might not even need the
optionsto be on the prototype in the first place. Just add it to your object in the constructor (theinitmethod), and be done with it:and once again, if you’re using jQuery or underscore, this becomes even simpler: