我创建了2个原型实例,在原型中更改了一个函数,两个实例中都反映了变化(很棒)。 但是,当我通过删除函数修改原型时,该函数仍然存在于现有实例中。
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());
第1行和第2行按预期工作,在将原型设置为空后,第4行显示未定义的预期值。 但是第3行仍然显示了函数定义。
答案 0 :(得分:5)
基本上,您重新分配函数prototype
的{{1}}属性以指向新对象。这不会影响旧对象,因此不会影响先前的实例。
以下是对正在发生的事情的说明。
执行此代码后:
A
情况如下:
然后执行此代码:
function A() {
this.name = "cool";
}
A.prototype = {
howCool: function() {
return this.name + "er";
}
};
var a1 = new A(),
a2 = new A();
A.prototype = {};
var a3 = new A();
指向新对象,但旧实例的[[Prototype]]属性仍指向旧对象。
如果要实际删除该方法,则必须编辑原始对象,而不是指向新对象。
要从原型中实际删除A.prototype
方法,可以使用以下方法:
howCool()
哪会给:
现在任何未来的实例,例如delete A.prototype.howCool
和之前的实例,仍将指向同一个对象,但该对象不会拥有a3
方法。
答案 1 :(得分:1)
如果您修改原型,它将影响旧实例,但如果您创建一个新实例,它将不会影响旧实例。
所以当你写:
A.prototype = {};
//line3
console.log(a1.howCool);
对象a1.__proto__
仍然指向最初的A.prototype
,这就是为什么它不会记录undefined
。
然后当你写:
//line4
var a3 = new A();
console.log(a3.howCool());
新实例a3
正在使用新创建的A.prototype
,这就是为什么你得到了'ndefined`。
答案 2 :(得分:0)
尝试使用delete
运算符
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);

答案 3 :(得分:0)
以下是可能的解释:
(注意:以下说明仅适用于实验和概念性理解,因为在生产代码中应避免使用__proto__)
如您所知,对象(在本例中为a1)与构造函数原型(在本例中为A)之间存在链接,从而创建了对象。
此链接称为__proto__
或dunder proto。所以在这种情况下,它可以被视为a1.__proto__
。
现在,发生的事情就是当你说A.prototype = {};
时,此时对象a1已经被构造,它通过这个链接指向A.prototype。
由于Javascript是垃圾收集语言,因此仅将A.prototype设置为{}并不会立即清理旧的protoytpe对象,因此较旧的对象仍然挥之不去。
因此,当您说console.log(a1.howCool());
时,howCool位于延迟对象中。
所以,如果你像这样修改你的line3:
// line3中
console.log(a1.__proto__);
a1.__proto__ = {};
console.log(a1.howCool());
您可以在行console.log(a1.__proto__);
的控制台窗口中看到旧的原型对象和howCool()
但是,如果设置a1.__proto__ = {};
,则console.log(a1.howCool());
将无法找到该对象,并且找不到howCool()(因为它现在设置为空对象)。
所以将A.prototype设置为{}并不能达到与a.__proto__
= {}相同的效果。
因此你看到了输出。
希望它有所帮助。