问题
I created 2 instances of a prototype, changed a function in prototype, changes reflected in both the instances (Great). However, when I modified the prototype by removing the function, the function still existed for the existing instances.
function A() {
this.name = "cool";
}
A.prototype = {
howCool: function() {
return this.name + "er";
}
};
var a1 = new A(),
a2 = new A();
a1.name = "hot";
//line1
console.log(a1.howCool());
//line2
console.log(a2.howCool());
A.prototype = {};
//line3
console.log(a1.howCool());
//line4
var a3 = new A();
console.log(a3.howCool());
Line 1 and 2 are working as expected and after setting the protoype back to empty, line 4 is showing undefined which is expected. line 3 however is still showing the function definition.
回答1:
Essentially you're reassigning the prototype
property for the function A
to point to a new object. This does not affect the old object and thus doesn't affect prior instances.
Here's an illustration of what is happening.
After this code executes:
function A() {
this.name = "cool";
}
A.prototype = {
howCool: function() {
return this.name + "er";
}
};
var a1 = new A(),
a2 = new A();
the situation is the following:
Then after this code executes:
A.prototype = {};
var a3 = new A();
The A.prototype
points to a new object but the [[Prototype]] property for old instances still points to the old object.
If you want to actually remove the method, you must edit the original object, not point to a new one.
To actually remove howCool()
method from the prototype, something like this would work:
delete A.prototype.howCool
Which would give:
Now any future instances, such as a3
, and the prior ones, would all still point to the same object but that object won't have the howCool()
method.
回答2:
Well if you modify the prototype it will affect the old instances, but if you create a new one it won't affect old instances.
So when you write:
A.prototype = {};
//line3
console.log(a1.howCool);
The object a1.__proto__
still points to the initial A.prototype
, that's why it doesn't log undefined
.
And then when you write :
//line4
var a3 = new A();
console.log(a3.howCool());
The new instance a3
is using the new created A.prototype
that's why you got ùndefined`.
回答3:
Try using the delete operator
function A(){
this.name = "cool";
}
A.prototype = {
howCool : function(){
return this.name + "er";
}
};
var a1 = new A(),
a2 = new A();
a1.name = "hot";
//line1
console.log(a1.howCool);
//line2
console.log(a2.howCool);
delete A.prototype.howCool;
//line3
console.log(a1.howCool);
//line4
var a3 = new A();
console.log(a3.howCool);
回答4:
Here is the possible explanation:
(Note: Below explanation is only for experiments and conceptual understanding as usage of __proto__ should be avoided in production code)
As you know that there is a link between an object(in this case a1) and the prototype of the constructor function( in this case A) out of which object is created.
This link is called __proto__
or dunder proto. So in this case it can be seen as a1.__proto__
.
Now, what is happening is that when you say A.prototype = {};
, at this time object a1 has already been constructed and it is pointing to A.prototype via this link.
Since Javascript is garbage collected language, merely setting A.prototype to {} isn't cleaning up the old protoytpe object right then and hence the older object is still lingering around.
So when you say console.log(a1.howCool());
, howCool is located in the lingering object.
So, if you modify your line3 like this:
//line3
console.log(a1.__proto__);
a1.__proto__ = {};
console.log(a1.howCool());
You would be able to see older prototype object and howCool() inside it in the console window in the line console.log(a1.__proto__);
However, if you set a1.__proto__ = {};
then console.log(a1.howCool());
will not be able to locate the object and howCool() would not be found(as it is now set to empty object).
So just setting A.prototype to {} isn't achieving the same effect as a.__proto__
= {}.
Hence the output that you see.
Hope it helps.
来源:https://stackoverflow.com/questions/43765005/javascript-modifying-prototype-doesnt-affect-existing-instances