2017-05-03 33 views
7

我创建了2个原型实例,更改了原型中的函数,更改反映在两个实例中(Great)。 但是,当我通过删除函数来修改原型时,该函数对于现有实例仍然存在。Javascript:修改原型不会影响现有实例

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是否按预期工作和设置protoype回空后,线4表示预计未定义。然而第3行仍然显示功能定义。

+6

您并未修改原型对象,而是创建了一个新对象。 – Bergi

+0

另请参见[与'instanceof'相同的混淆](http://stackoverflow.com/q/14568239/1048572)和[如何正确定义Javascript原型](http://stackoverflow.com/q/17474390/ 1048572) – Bergi

+2

您实际上已将原型属性重新分配给一个新对象。旧的仍然存在。 – abhishekkannojia

回答

5

实质上,您将重新指定函数Aprototype属性以指向新对象。这不会影响旧对象,因此不会影响先前的实例。

下面是对正在发生的事情的说明。

此代码后执行:

function A() { 
    this.name = "cool"; 
} 

A.prototype = { 
    howCool: function() { 
    return this.name + "er"; 
    } 
}; 

var a1 = new A(), 
    a2 = new A(); 

的情况如下:再经过

before

代码执行:

A.prototype = {}; 

var a3 = new A(); 

A.prototype点到一个新的对象但是旧实例的属性仍指向旧对象。

after

如果你想真正去除方法,你必须编辑原始对象,而不是指向一个新的。

要真正原形从howCool()方法,像这样的工作:

delete A.prototype.howCool 

这将使:

finally

现在,任何未来的实例,例如a3,而先前的那些,都将仍然指向相同的对象,但该对象将不具有howCool()方法。

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);

+0

或'A.prototype.howCool = undefined;'。 – GramThanos

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`新的实例。

0

下面是可能的解释:
(注:下面的解释是只为实验和概念理解为__proto__的使用应在生产代码来避免)

如你所知,有之间的联系一个对象(在本例中为a1)以及创建该对象的构造函数的原型(在本例中为A)。 此链接被称为__proto__或dunder proto。所以在这种情况下可以看作a1.__proto__

现在发生的事情是,当你说A.prototype = {};时,此时对象a1已经被构建,并且它通过这个链接指向A.prototype。

由于JavaScript是垃圾收集语言,只是将A.prototype设置为{}并没有清理旧的protoytpe对象,因此旧对象仍然徘徊不前。 所以当你说console.log(a1.howCool());时,howCool位于滞留物体中。

因此,如果您修改3号线这样的:

// 3号线

console.log(a1.__proto__); 
a1.__proto__ = {}; 
console.log(a1.howCool()); 

你就可以看到旧的原型对象和howCool()里面在控制台窗口中的行console.log(a1.__proto__); 但是,如果您设置了a1.__proto__ = {};,则console.log(a1.howCool());将无法​​找到该对象,并且找不到howCool()(因为它现在设置为空对象)。

因此,将A.prototype设置为{}并不会达到与a.__proto__ = {}相同的效果。

因此,你看到的输出。

希望它有帮助。

+0

请不要使用'__proto__',它已被弃用并产生错误的展示。使用标准的'Object.getPrototypeOf'。 – Bergi

+0

@Bergi当然,我不打算使用它。这只是为了解释OP看到的行为背后的原因。我只是不想将他与其他细节混淆。他更容易在控制台窗口中的a1对象上看到此属性。 –

+0

除*它不是一个实际的属性,因此混淆imo。 – Bergi

相关问题