可能重复:
Why are my JS object properties being overwritten by other instances
为什么调用setT后属性“t”没有改变?我希望“4”作为输出,但它打印“默认”。
function Car(i) {
var id = i;
var t = "default";
this.getT = function() { return t; }
this.setT = function(p) {
t = p; // attribute t isn't changed ..
}
}
function ECar(id) {
Car.call(this, id); // super constructor call
this.setT = function(p) { // override
ECar.prototype.setT.call(this, p); // super call
}
}
ECar.prototype = new Car();
ecar = new ECar(3);
ecar.setT(4);
alert(ecar.getT()); // prints default, not 4
答案 0 :(得分:4)
ECar.prototype = new Car();
在此行ECar
的原型中获取一个上下文,其中将共享所有ECar
的实例。
ECar.prototype.setT.call(this, p);
这一行会调用那个上下文,而不是在Car.call(this, id);
调用 super 时创建的内容。
您可以使用
修复代码function ECar(id) {
Car.call(this, id); // super constructor call
var carSetT = this.setT;
this.setT = function(p) {
carSetT.call(this, p);
}
}
但使用真实的原型会更好(也更可读),例如
function Car() {}
Car.prototype.getT = function () { /* ... */ };
Car.prototype.setT = function () { /* ... */ };
function ECar() {}
ECar.prototype = new Car();
ECar.prototype.setT = function () { /* ... */ };
修改:注意(如@Bergi建议的那样)
如果您必须支持旧版浏览器,那么您应该只使用Child.prototype = new Parent()
作为继承。那么你应该只使用空构造函数。
JavaScript中用于继承的最多(其他语言)兼容方式是
Child.prototype = Object.create(Parent.prototype)
(MDN表示它来自IE 9)
答案 1 :(得分:2)
// attribute t isn't changed ..
请注意t
不是“属性”,而是构造函数范围(“私有”)本地的变量。
ECar.prototype.setT.call(this, p); // super call
不符合您的预期。您似乎想要更改通过调用超级构造函数创建的变量(它仍然是该变量环境的本地变量,并且由构造函数中创建的的getT
和setT
函数公开。现在,您正在调用在行ECar.prototype = new Car();
中创建的函数 - 它会更改在那里创建的变量t
。您call
上的函数当前对象无关紧要,因为它不使用this
关键字。
所以,你不想a)使用那个原型Car的方法,但你自己和b)根本不想为原型创建Car
的实例。另见What is the reason [not] to use the 'new' keyword here?。在当前实例上应用超级构造函数就足够了。如果要在仍然使用旧方法的同时扩展方法,则需要将它们(以及它们)保存在变量中。
function Car(id) {
var t = "default";
this.getT = function () {
return t;
};
this.setT = function (p) {
t = p;
};
}
function ECar(id) {
Car.call(this, id); // super constructor call
var oldSetter = this.setT;
this.setT = function (p) { // override
oldSetter(p); // call the function which access this instance's "t"
}
}
ECar.prototype = Object.create(Car.prototype, {constructor: {value: ECar}});
var ecar = new ECar(3);
ecar.setT(4);
console.log(ecar.getT()); // prints 4
答案 2 :(得分:0)
function Car(i) {
var id = i;
var t = "default";
this.getT = function() { return t; }
this.setT = function(p) {
t = p; // attribute t isn't changed ..
}
}
function ECar(id) {
Car.call(this, id); // super constructor call
}
ECar.prototype = new Car();
ECar.prototype.constructor = ECar; //Never forget doing this
ecar = new ECar(3);
ecar.setT(4);
alert(ecar.getT());
您无需覆盖setT功能。