问题
I understand what prototypal inheritance is all about, but I must be confused as to the implementation. I thought that modifying a function constructor's prototype would affect all instances of that constructor, but this isn't the case. How does JS do the method lookup from an object to its prototype?
Here's an example
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
I was under the impression that a
would look for the method talk()
in A
's prototype, so any modification to A
's prototype, before or after a
was instantiated would be reflected, but this doesn't seem to be the case. Can someone explain this for me?
回答1:
It's the difference between modifying and replacing the prototype.
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
Here is what is going on:
// 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.
回答2:
In support of Sean's good answer: there's nothing wrong with replacing the entire prototype, as long as you do it before you create instances of the object. This also works:
function A(name){
this.name = name;
}
A.prototype = {
talk: function(){
return "hello " + this.name;
}
}
a = new A("brad");
a.talk() // works
Just be sure not to replace it later (unless that's what you're trying to do).
In your original example A
didn't have your custom prototype at the time you created your first instance, but it did have it when you created your second one, because you created the prototype in between.
The prototype chain is established when an object is instantiated, so it's possible for two instances of the same "class" to have different prototypes, as you demonstrated.
This can cause all kinds of trouble:
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
The object referred to by a
is no longer considered an instance of A
because instanceof
works by checking if A.prototype
is in the prototype chain of a
.
来源:https://stackoverflow.com/questions/5185122/prototypal-inheritance-question-in-javascript