gpt4 book ai didi

javascript - 设置继承自prototype的属性值,为什么prototype的值没有变化?

转载 作者:行者123 更新时间:2023-11-29 18:08:11 27 4
gpt4 key购买 nike

我在 Chrome 中做了一些测试。很简单,我更改继承的属性值。我假设集合会发生在原型(prototype)对象上,但原型(prototype)值不会改变。

实际上是在子对象上创建了一个新属性。这是预期的吗?

> function Shape() {};
> var base = new function() { this.mValue = 10; };
> Shape.prototype = base;
> var s = new Shape();
> s.mValue = 20;
> base;

< Object {mValue: 10}

最佳答案

Set the property value inherited from prototype, why the prototype value does not change?

因为当您分配给 s.mValue 时,它会在 s 上创建一个属性,它会遮盖原型(prototype)上的属性。

属性访问是这样的:

  • 如果您要获取属性的值,它会首先查看对象本身,看它是否拥有该属性。如果是,它返回该对象的值。如果没有,它会查看对象的原型(prototype)并返回原型(prototype)的值(如果原型(prototype)有);如果不是,则转到原型(prototype)的原型(prototype),依此类推。

  • 如果您要设置属性的值,它会在对象本身上设置它,它不会沿着原型(prototype)链上升。

显然这是简单的版本。 :-)

如果您是从基于类的语言开始学习的,这可能会有点令人惊讶,但是一旦您理解了它,它就真的很简单。

为了清楚起见,让我们对其进行一些 ASCII 艺术处理。在这段代码之后:

function Shape() {};
var base = new function() { this.mValue = 10; };
Shape.prototype = base;

...我们在内存中有这样的东西:

        +−−−−−−−−−−−−−−−−−−+                  Shape−−>|     function     |                          +−−−−−−−−−−−−−−−−−−+        | [[Prototype]]    |−−−−−> Function.prototype        | prototype        |−+          +−−−−−−−−−−−−−−−−−−+ |    +−−−−−−−−−−−−−−−+                                                 +−−−>|    object     |                                                 |    +−−−−−−−−−−−−−−−+                    base−−−−−−−−−−−−−−−−−−−−−−−−−+    | [[Prototype]] |−−−> Object.prototype                                  | mValue: 10    |                                                      +−−−−−−−−−−−−−−−+                    

(If prototype vs. [[Prototype]] is unfamiliar to you, see the explanation at ¹ at the end of the answer.)

Then we do:

var s = new Shape();

并得到:

        +−−−−−−−−−−−−−−−−−−+                  Shape−−>|     function     |                          +−−−−−−−−−−−−−−−−−−+        | [[Prototype]]    |−−−−−> Function.prototype        | prototype        |−+          +−−−−−−−−−−−−−−−−−−+ |    +−−−−−−−−−−−−−−−+                                                 +−+−>|    object     |                                                 | |  +−−−−−−−−−−−−−−−+                    base−−−−−−−−−−−−−−−−−−−−−−−−−+ |  | [[Prototype]] |−−−> Object.prototype                               |  | mValue: 10    |                            +−−−−−−−−−−−−−−−−−−+   |  +−−−−−−−−−−−−−−−+                    s−−−−−−>|      object      |   |                +−−−−−−−−−−−−−−−−−−+   |        | [[Prototype]]    |−−−+        +−−−−−−−−−−−−−−−−−−+

At this point, if we did console.log(s.mValue), the JavaScript engine would look at s and, not finding a property with the name mValue, it would follow the __proto__ link to get the prototype, and look there. Finding it there, it gets the value from there.

Then we do:

s.mValue = 20;

并得到:

        +−−−−−−−−−−−−−−−−−−+                  Shape−−>|     function     |                          +−−−−−−−−−−−−−−−−−−+        | [[Prototype]]    |−−−−−> Function.prototype        | prototype        |−+          +−−−−−−−−−−−−−−−−−−+ |    +−−−−−−−−−−−−−−−+                                                 +−+−>|    object     |                                                 | |  +−−−−−−−−−−−−−−−+                    base−−−−−−−−−−−−−−−−−−−−−−−−−+ |  | [[Prototype]] |−−−> Object.prototype                               |  | mValue: 10    |                            +−−−−−−−−−−−−−−−−−−+   |  +−−−−−−−−−−−−−−−+                    s−−−−−−>|      object      |   |                +−−−−−−−−−−−−−−−−−−+   |        | [[Prototype]]    |−−−+        | mValue: 20       |        +−−−−−−−−−−−−−−−−−−+

At this point, if we did console.log(s.mValue), the JavaScript engine would look at s, find the property, and get its value from s.


Side note: var base = new function() { this.mValue = 10; }; is a really long way to write var base = { mValue: 10 }. ;-) And it very very very slightly slows down access to the properties inherited from Object.prototype, as it inserts an extra unnecessary prototype in the chain. Also, you don't need to create a new object for Shape to assign to instances; it already has one.

So that code can be simplified to:

function Shape() {} // No need for ; after function declarations, they're not statements
Shape.prototype.mValue = 10;
var s = new Shape();
s.mValue = 20;
Shape.prototype;

(截至 2023 年对答案的更新,我们可能不会使用 var。)

只是 FWIW。


¹ 关于 prototype[[Prototype]]:

  • prototype 是一些函数所具有的属性,它指向要分配的对象,作为通过 new 使用该函数创建的对象的原型(prototype)。示例:Date.prototype 指向用作通过new Date 创建的日期实例的原型(prototype)的对象。
  • [[Prototype]] 是对象的内部字段,指向对象的原型(prototype)。示例:如果您执行了 const d = new Date()d'[[Prototype]] 字段指向 Date。原型(prototype)[[Prototype]] 字段不能直接在代码中访问。您可以使用 Object.getPrototypeOf(d) 访问它,或者(不推荐)使用 Object.prototype 中定义的名为 __proto__ 的访问器属性来访问它>。 (但不要在新代码中使用 __proto__。它只是为了向后兼容为 JavaScript 引擎编写的代码,该引擎在标准化之前添加了该功能,因此没有必要,并注意不继承的对象来自 Object.prototype 没有它。)

关于javascript - 设置继承自prototype的属性值,为什么prototype的值没有变化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29790292/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com