我真的没有进行JavaScript原型设计。拿这个代码,例如:
function Class(asdf) {
if(typeof(asdf) == 'undefined') {
} else {
this.asdf = asdf;
}
}
Class.prototype.asdf = "default_asdf";
Class.prototype.asdf2 = [];
Class.prototype.change_asdf = function() {
this.asdf = "changed_asdf";
this.asdf2.push("changed_asdf2");
}
function SubClass() {
}
SubClass.prototype = new Class("proto_class");
SubClass.prototype.constructor = SubClass;
test1 = new SubClass();
alert("test1 asdf: " + test1.asdf + " " + test1.asdf2);
test1.change_asdf();
alert("test1 asdf: " + test1.asdf + " " + test1.asdf2);
test2 = new SubClass();
alert("test2 asdf: " + test2.asdf + " " + test2.asdf2);
第一个警告按预期打印“proto_class []”。第二个警告也按预期打印“changed_asdf [changed_asdf2]”。但为什么第三个警告打印“proto_class [changed_asdf2]”?!如果正在修改原始原型对象(新类(“proto_class”)),那么asdf变量为什么不保留“changed_asdf”?如果不是,为什么asdf2数组包含“changed_asdf2”?此外,我如何确保每个新的SubClass()实例包含一个新的Class()实例,如在C ++和Java中?
答案 0 :(得分:1)
这是因为你写了
SubClass.prototype = new Class("proto_class");
您正在创建一个实例 Class
的原型。你想要的是创建一个继承其父类原型的子类。正如David Flanagan在他的JavaScript: The Definitive Guide(第9.5节)中所示,你必须使用辅助函数来创建一个具有指定原型的新对象:
function heir(p) {
function f(){} // dummy constructor function
f.prototype = p; // specify prototype object we want
return new f(); // create and return new object
}
(Crockford在所谓的ES5 object constructor property之后调用此函数Object.create
,但请不要这样做can be misleading。)
在SubClass构造函数中,您必须call将this
设置为当前对象的Class构造函数:
function SubClass() {
// call the parent's constructor with
// `this` set to the current scope
Class.call(this, "proto_class");
}
最后,但并非最不重要的是,您只需重置Class.asdf2
一次,但不会重置Class
或SubClass
的构造函数。所以将this.asdf2 = [];
添加到其中一个构造函数中。
完整的代码现在为:
function heir(p) {
function f(){} // dummy constructor function
f.prototype = p; // specify prototype object we want
return new f(); // create and return new object
}
function Class(asdf) {
if (typeof asdf != 'undefined')
this.asdf = asdf;
}
Class.prototype.asdf = "default_asdf";
Class.prototype.asdf2 = [];
Class.prototype.change_asdf = function() {
this.asdf = "changed_asdf";
this.asdf2.push("changed_asdf2");
}
function SubClass() {
// call the parent's constructor with
// `this` set to the current scope
Class.call(this, "proto_class");
this.asdf2 = [];
}
SubClass.prototype = heir(Class.prototype);
SubClass.prototype.constructor = SubClass;
test1 = new SubClass();
alert("test1 asdf: " + test1.asdf + " " + test1.asdf2);
test1.change_asdf();
alert("test1 asdf: " + test1.asdf + " " + test1.asdf2);
test2 = new SubClass();
alert("test2 asdf: " + test2.asdf + " " + test2.asdf2);
答案 1 :(得分:0)
这是因为asdf2
是Class.prototype
上的可变数组。该数组由委托给该原型的所有实例共享。如果您希望每个实例都有一个单独的asdf2
,则必须在某种方法中将其分配给this.asdf2
。
请注意,您指定了this.asdf
,但从未指定this.asdf2
,只需按下现有数组即可。
var house = {nice: true};
var me = {home: house};
var roomie = {home: house};
// Now roomie has a party and trashes the place.
roomie.home.nice = false;
//and how's my house?
me.home.nice === false;
// because house is shared.
此示例中house
的共享与问题中asdf2
的共享相同。