function Foo() {}
Foo.prototype.x = 1
foo = new Foo()
foo2 = new Foo()
foo2.x = 2
Foo.prototype.x = 3
console.log("foo.x = ", foo.x)
console.log("foo2.x = ", foo2.x)
=> foo.x = 3
=> foo2.x = 2
上面创建了两个对象,更新了一个对象的inherited property
,然后更新了它们的prototype's property
。为什么更新后的对象会保留自己的新值,而另一个跟踪prototype's
?
@EDIT
上述表达式the inherited property of one object is updated
在上述情况下似乎具有误导性。
事实上,即使shadow property
已经包含object
,当{1}}设置为本地不存在的property
时,也会在prototype
上创建prototype's properties
。在这种情况下,从object
的角度来看,local shadow property
只是准备就绪。之后,此{{1}}可以直接访问。
答案 0 :(得分:4)
为什么更新的对象会保留自己的新值,但另一个跟踪原型的?
因为x
属性直接设置在foo2
和阴影原型的x
属性上。
console.dir(foo2)
并亲自看看:
Foo
x: 2
__proto__: Foo
constructor: function Foo() {}
x: 3
__proto__: Object
console.dir(foo)
显示:
Foo
__proto__: Foo
constructor: function Foo() {}
x: 3
__proto__: Object
当您尝试访问属性时,将始终返回最接近原型链中对象的值。
可以在§8.12.2 of the ECMAScript 5.1 specification中找到确切的算法。
答案 1 :(得分:1)
如果没有在当前实例上明确定义,JavaScript将只查看原型来解析属性调用。
由于.x
被定义为foo2为2
,因此它不会再查看该值。
但是,对于foo,.x
未在实例上定义,因此它会查看原型,并获得3。
答案 2 :(得分:1)
这是一个很好的问题,无论如何答案很简单:因为foo2
对象有一个名为x
的属性,它有自己的值并且不是从原型继承的。如果要访问原型值,则应执行foo1.constructor.prototype.x
。你必须想象这样的结构:
变量如下所示:
如果JS在对象中找不到x
属性,那么它将查看原型内部。
答案 3 :(得分:0)
您从未设置foo.x
,因此默认prototype
值取决于.log()
,3
。
如果你去
foo.x = 10
foo2.x = 2
Foo.prototype.x = 3
...然后检查foo.x
,它是10,因为它已被明确覆盖。
作为必然结果,如果您未设置foo2.x
,它也将是3
:
...
//foo2.x = 2
Foo.prototype.x = 3
...
如果事情不起作用,那就意味着.prototype
属性在实例化后是只读的,所以你有不同版本的默认值,这取决于你实例化的时间和/或改变了财产。没有乐趣。
当您明确覆盖它时,您会知道它何时以及为何被更改。否则,使用当前设置.prototype
。