我遇到了一个奇怪的代码片段,我完全无法理解,如下所示:
var obj = function() {};
obj.prototype.x = 5;
var instance1 = new obj();
obj.prototype = {y: 6};
var instance2 = new obj();
console.log(instance1.x, instance1.y, instance2.x, instance2.y);
// 5, undefined, undefined, 6现在的问题是:
5, undefined, undefined, 6而不是undefined, 6, undefined, 6每一种解释都很感激。
发布于 2014-10-12 11:13:49
据ECMA脚本5规范称,
在函数对象作为新创建对象的构造函数被调用之前,
prototype属性的值用于初始化新创建对象的[[Prototype]]内部属性。
很明显,prototype只是初始化[[Prototype]]属性。在创建对象时,将[[Prototype]]设置为构造函数的prototype对象,并建立原型链。在你的情况下,当你这样做
var obj = function() {};
obj.prototype.x = 5;
var instance1 = new obj();[[Prototype]]看起来像这样
console.log(Object.getPrototypeOf(instance1));
# { x: 5 }(是的,您可以使用[[Prototype]]函数访问Object.getPrototypeOf )
因此,当JS引擎在instance1中查找instance1时,它会找到5的值,并且由于y没有定义,所以它使用undefined。
在第二个案例中,
obj.prototype = {y: 6};
var instance2 = new obj();您正在更改prototype对象的obj,以便使用此函数构造的新对象将使用分配给它的新对象。所以,[[Prototype]]看起来像这样,对于instance2来说
console.log(Object.getPrototypeOf(instance2));
# { y: 6 }这就是为什么,instance2在里面找不到x,但是y。
为了回答最新的问题,
编辑:我将如何改变所有实例的原型?
您可以用Object.setPrototypeOf更改旧对象的原型,如下所示
Object.setPrototypeOf(instance1, {
y: 6
});因为,这使得[[Prototype]] of instance1不同于instance2,所以我们只需更新构造函数的prototype对象,如下所示
delete obj.prototype.x;
obj.prototype.y = 6;现在,我们没有改变instance1和instance2的内部属性。我们可以这样检查
console.log(Object.getPrototypeOf(instance1) === Object.getPrototypeOf(instance2));
# true
console.log(Object.getPrototypeOf(instance1) === obj.prototype);
# true注释:惯例是用大写字母命名构造函数。
发布于 2014-10-12 11:00:27
解释
因此,首先,您的两行代码创建一个函数obj,并将其分配给它的原型{x: 5}。
当您创建此对象的实例时,它似乎有一个对原型的内部引用,该原型是new'd时存在的。
在此之后,您将原型重新分配到{y: 6},这不影响对第一个原型的instance1内部引用。
然后,当您创建instance2时,它有一个对第二个原型的内部引用,因此,记录它们将生成5, undefined, undefined, 6。
#4
您可以,而不是将原型重新分配到一个新对象:
obj.prototype = {y: 6};改为修改原型:
delete obj.prototype.x; // Setting to undefined should produce same behaviour
obj.prototype.y = 6;这将产生输出:undefined, 6, undefined, 6
我已经用Chrome上的http://jsfiddle.net/9j3260gp/和Windows上的火狐最新版本对此进行了测试。
发布于 2014-10-12 11:00:25
prototype是一种与后台新特性相结合的特性。它适用于与new一起使用的该函数的所有实例。在第一个示例中,将.x =5附加到原型中,所创建的实例的值为.x =5。稍后,您将原型修改为一个新对象。这就是在任何新实例中使用的原型。这就是为什么第一个实例只有.x = 5,第二个实例只有.y =6。
https://stackoverflow.com/questions/26324395
复制相似问题