我理解什么是原型继承,但我必须对实现感到困惑。我认为修改函数构造函数的原型会影响该构造函数的所有实例,但事实并非如此。 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
我认为a
会在talk()
的原型中寻找方法A
,因此对A
的原型进行任何修改,无论是之前还是之后实例化的a
会被反映出来,但似乎并非如此。有人可以帮我解释一下吗?
答案 0 :(得分: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.
答案 1 :(得分: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
是否在{{1}的原型链中而起作用}。