我在Chrome中做了一些测试。很简单,我改变了继承的属性值。我假设设置会发生在原型对象上,但是原型值没有改变。
实际上在子对象上创建了一个新属性。这是预期的吗?
> function Shape() {};
> var base = new function() { this.mValue = 10; };
> Shape.prototype = base;
> var s = new Shape();
> s.mValue = 20;
> base;
< Object {mValue: 10}
1条答案
按热度按时间qni6mghb1#
设置继承自prototype的属性值,为什么prototype值不变?
因为当你赋值给
s.mValue
时,它会在s
上创建一个 * new * 属性,这个属性隐藏了原型上的属性。属性访问的工作方式如下:
显然这是简单的版本。:-)
如果您是从基于类的语言开始使用它,这可能会有点令人惊讶,但是一旦您理解了它,它就真的很简单了。
为了清楚起见,让我们使用一些ASCII艺术。
......我们的记忆中有这样的东西:
prototype
与[[Prototype]]
,请参见答案末尾¹处的解释。)*然后我们做:
并得到:
此时,如果我们使用
console.log(s.mValue)
,JavaScript引擎将查看s
,如果没有找到名为mValue
的属性,它将沿着__proto__
链接获取原型,并查看那里,如果在那里找到它,它将从那里获取值。然后我们做:
并得到:
此时,如果我们执行
console.log(s.mValue)
,JavaScript引擎将查看s
,找到属性,并从s
获取其值。旁注:
var base = new function() { this.mValue = 10; };
比写var base = { mValue: 10 }
真的长。- )而且它 * 非常非常轻微地 * 减慢了对从Object.prototype
继承的属性的访问,因为它在链中插入了一个额外的不必要的原型,而且,你不需要为Shape
创建一个新的对象来分配给示例;它已经有了一个。因此代码可以简化为:
(And在2023年更新答案时,我们可能不会使用
var
。)只是FWIW。
¹关于
prototype
和[[Prototype]]
:prototype
是某些函数具有的属性,它指向要指定为通过new
使用函数创建的对象原型的对象。示例:Date.prototype
指向用作通过new Date
创建的日期示例原型的对象。[[Prototype]]
是指向对象原型的对象内部字段。例如:如果您使用const d = new Date()
,d'
的[[Prototype]]
字段将指向Date.prototype
。[[Prototype]]
字段无法在代码中直接访问。您可以使用Object.getPrototypeOf(d)
访问它。或(不推荐),方法是使用在Object.prototype
中定义的名为__proto__
的访问器属性。(但是不要在新代码中使用__proto__
,这只是为了向后兼容为JavaScript引擎编写的代码,该引擎在标准化之前添加了该特性,并且注意,没有从Object.prototype
继承的对象不具有该特性。)