3

我了解原型继承的全部意义,但我必须对实现感到困惑。我认为修改函数构造函数的原型会影响该构造函数的所有实例,但事实并非如此。JS 是如何从一个对象到它的原型进行方法查找的呢?

这是一个例子

function A(name){
  this.name = name;
}

a = new A("brad");

A.prototype = {
  talk: function(){
    return "hello " + this.name;
  }
}

a.talk() // doesn't work
b = new A("john");
b.talk() // works

我的印象是会在's 的原型中a寻找方法,因此在实例化之前或之后对 ' 原型的任何修改都会反映出来,但情况似乎并非如此。有人可以为我解释一下吗?talk()AAa

4

2 回答 2

4

这是修改替换原型之间的区别。

function A(name){
  this.name = name;
}

a = new A("brad");
// Change, don't replace.
A.prototype.talk = function(){
    return "hello " + this.name;
};

a.talk() // works
b = new A("john");
b.talk() // works

这是发生了什么:

// Continued from above
var old_proto = A.prototype;

// Nuke that proto
A.prototype = {
talk: function() {
    return "goodbye " + this.name;
}
};

var c = new A("Al");

a.talk() // hello brad
b.talk() // hello john
c.talk() // goodbye Al

old_proto.say_goodbye = function() {
    return "goodbye " + this.name;
};

a.say_goodbye() // goodbye brad
b.say_goodbye() // goodbye john
c.say_goodbye() // TypeError c.say_goodbye is not a function.
于 2011-03-03T18:53:26.010 回答
3

支持 Sean 的好回答:替换整个原型没有任何问题,只要您在创建对象实例之前执行此操作即可。这也有效:

function A(name){
  this.name = name;
}

A.prototype = {
  talk: function(){
    return "hello " + this.name;
  }
}

a = new A("brad");

a.talk() // works

只要确保以后不要更换它(除非这是你想要做的)。

在您的原始示例A中,您在创建第一个实例时没有自定义原型,但在创建第二个实例时它确实有,因为您在两者之间创建了原型。

原型链是在实例化对象时建立的,因此如您所演示的,同一“类”的两个实例可能具有不同的原型。

这可能会导致各种麻烦:

var a = new A("brad");
console.log(a instanceof A) // true

A.prototype = {
  talk: function(){
    return "hello " + this.name;
  }
}

console.log(a instanceof A) // false

引用的对象a不再被视为 的实例,A因为instanceof通过检查是否A.prototype在 的原型链中来工作a

于 2011-03-03T19:04:48.077 回答