我使用原型继承,并希望拥有带有实例数组的对象。因此,如果我从一个具有实例数组的对象派生一些对象并访问该数组,则所有这些对象都共享该数组。我想把一些东西推到数组中,只改变实际对象中的数组,而不是所有其他对象。
使用标准原型继承和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.add(2);
sys.puts(other.data.length); // is 2, but should be 1
答案 0 :(得分:2)
var ObjectName = function(){
this.data = [];
}
ObjectName.prototype.add = function(what){
this.data.push(what);
};
var one = new ObjectName();
one.add(1);
答案 1 :(得分:1)
Object.create
没有优雅的解决方案,因为你做错了。
你想要的是:
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);
...
答案 2 :(得分:0)
您也可以替换:
add: function(what) { // prototype methods here
this.data.push(what);
}
与
add: function(what) { // prototype methods here
this.data = this.data.concat(what);
}
因为这将创建一个新变量,而不是将其推入原型的实例。
答案 3 :(得分:0)
Object.create
可以通过传递带属性描述符的第二个参数来为新对象添加属性。
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
当然,您可能希望将其放在构建器函数中,这样您就不会重复:
function makeThing() {
return Object.create(obj, {
data: {
value: [],
writable: true,
enumerable: true,
configurable: true
}
});
}
尽管如此,你基本上是在编写一个构造函数(其优点是你不需要用new来调用它)。此外,如果您将writable
,enumerable
和configurable
设置为true
,则可以按正常方式设置属性,这可以向后兼容ECMAScript 3实现了Object.create
的简单版本:
function makeThing() {
var newObj = Object.create(obj);
newObj.data = [];
return newObj;
}