问题
Possible Duplicate:
Why are my JS object properties being overwritten by other instances
Why isn't the attribute "t" changed after setT was called? I would expect "4" as output, but it prints "default".
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
回答1:
ECar.prototype = new Car();
At this line ECar's prototype get a context, in which all ECar's instance will be shared.
ECar.prototype.setT.call(this, p);
This line will call at that context, not what has been created while calling super at Car.call(this, id);.
You can fix your code with
function ECar(id) {  
  Car.call(this, id);  // super constructor call
  var carSetT = this.setT;
  this.setT = function(p) {
    carSetT.call(this, p);
  }
}
but it would be better (and more readable) to use real prototypes, such as
function Car() {}
Car.prototype.getT = function () { /* ... */ };
Car.prototype.setT = function () { /* ... */ };
function ECar() {}
ECar.prototype = new Car();
ECar.prototype.setT = function () { /* ... */ };
Edit: note (as @Bergi suggested)
You should only use Child.prototype = new Parent() as inheritance if you must support legacy browsers & then you should only use empty constructors.
The most (other-language) compatible way in JavaScript for inheritance is
Child.prototype = Object.create(Parent.prototype)
(MDN says it is supprted from IE 9)
回答2:
// attribute t isn't changed ..
Please notice that t is not an "attribute", but a variable local to the constructors scope ("private").
ECar.prototype.setT.call(this, p); // super call
does not work how you expect it. You seem to want to change the variable created with the call to your super constructor (it's still local to that variable environment, and exposed by the getT and setT functions that were created in the constructor. So now, you are calling the function that was created in the line ECar.prototype = new Car(); - which changes the variable t that was created there. That you call the function on the current object does not matter, as it does not use the this keyword inside.
So, you don't want to a) use the method of that prototype Car, but your own and b) don't want to create an instance of Car for the prototype at all. See also What is the reason [not] to use the 'new' keyword here?. To apply the super constructor on your current instance is enough. If you want to extend the methods while still using the old ones, you need to preserve them (and exactly them) in a variable.
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
回答3:
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());
You don't need to override setT function. 
来源:https://stackoverflow.com/questions/13167386/set-attribute-with-javascript-super-method