Javascript : Modifying Prototype doesn't affect existing Instances [duplicate]

五迷三道 提交于 2021-01-27 04:29:07

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!