使用javascript super方法设置属性

时间:2012-10-31 21:03:25

标签: javascript super

  

可能重复:
  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

3 个答案:

答案 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

不符合您的预期。您似乎想要更改通过调用超级构造函数创建的变量(它仍然是该变量环境的本地变量,并且由构造函数中创建的getTsetT函数公开。现在,您正在调用在行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功能。