3
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

@编辑

上面的表达式 ,the inherited property of one object is updated在上面的上下文中似乎具有误导性。

实际上,当设置了本地不存在 的 a 时,即使已经包含它,shadow property也会在 上创建a。在这种情况下,从. 之后,这具有立即被访问的权利。objectpropertyprototypeprototype's propertiesobjectlocal shadow property

4

4 回答 4

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

当你试图访问一个属性时,总是会返回最接近原型链中对象的值。

确切的算法可以在ECMAScript 5.1 规范的 §8.12.2 中找到。

于 2013-06-14T08:32:26.530 回答
1

如果没有在当前实例上专门定义属性调用,JavaScript 只会查看原型来解决属性调用。

由于.x是为 foo2 定义的2,它不再寻找该值。但是,对于 foo,.x没有在实例上定义,所以它查看原型,并得到 3。

于 2013-06-14T08:32:33.453 回答
1

这是一个很好的问题,无论如何答案很简单:因为foo2对象有一个名为的属性x,它有自己的值并且不是从原型继承的。如果你想访问你应该做的原型值foo1.constructor.prototype.x。你必须想象这样的结构:

  • Foo.prototype
    • Foo.prototype.x

变量如下所示:

  • 富 = {}
  • foo2 = {x:2}

如果 JS 没有x在对象中找到该属性,那么它将在原型内部查找。

于 2013-06-14T08:34:59.243 回答
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

于 2013-06-14T08:31:24.573 回答