Problem with prototypal inheritance and instance array [duplicate]
I use prototypal inheritance and want to have objects with instance arrays. So if I derive some objects from one object with an instance array and access the array, all of them share the array. I want to push something to the array and only change the array in the actual object, not in all others.
What is a elegent solution to this Problem with using standard prototypal inheritance and Object.create?
var sys = require('sys');
var obj ={
data: [],
add: function(what){
this.data.push(what)
}
};
var one = Object.create(obj);
one.add(1);
var other = Object.create(obj);
other.开发者_Python百科add(2);
sys.puts(other.data.length); // is 2, but should be 1
var ObjectName = function(){
this.data = [];
}
ObjectName.prototype.add = function(what){
this.data.push(what);
};
var one = new ObjectName();
one.add(1);
There is no elegant solution with Object.create, because You're Doing It Wrong.
What you want is:
function MyArray() {
this.data = []; // per-instance data here
}
MyArray.prototype = {
add: function(what) { // prototype methods here
this.data.push(what);
}
};
var one = new MyArray;
one.add(1);
...
You can also replace:
add: function(what) { // prototype methods here
this.data.push(what);
}
with
add: function(what) { // prototype methods here
this.data = this.data.concat(what);
}
as this will create a new variable instead of pushing it into it the prototype's instance.
Object.create can add properties to the new object, by passing a second parameter with property descriptors.
var sys = require('sys');
var obj = {
add: function(what){
this.data.push(what)
}
};
var one = Object.create(obj, {
data: {
value: [],
writable: true,
enumerable: true,
configurable: true
}
});
one.add(1);
var other = Object.create(obj, {
data: {
value: [],
writable: true,
enumerable: true,
configurable: true
}
});
other.add(2);
sys.puts(other.data.length); // should be 1
Of course, you would want to put that in a builder function so you don't repeat yourself:
function makeThing() {
return Object.create(obj, {
data: {
value: [],
writable: true,
enumerable: true,
configurable: true
}
});
}
Although, at at point you're basically writing a constructor (with the advantage that you don't need to call it with new). Also, if you're setting writable, enumerable, and configurable to true, you could just set the property the normal way, which can be made backward-compatible with ECMAScript 3 by implementing a simple version of Object.create:
function makeThing() {
var newObj = Object.create(obj);
newObj.data = [];
return newObj;
}
加载中,请稍侯......
精彩评论