简体   繁体   English

JavaScript obj.constructor vs obj.[[Prototype]] 的构造函数

[英]JavaScript obj.constructor vs obj.[[Prototype]]'s constructor

Object.getPrototypeOf(z).constructor === z.constructor

Is this true for every object z in JavaScript?这对于 JavaScript 中的每个 object z是否都是如此?

I mean is z.constructor just a shortcut allowing us to retrieve more easily我的意思是z.constructor只是一个让我们更容易检索的快捷方式
the constructor property of the object's internal [[Prototype]] property.对象内部[[Prototype]]属性的构造函数属性。

Or... are there cases in which the two differ and the z.constructor value或者...是否存在两者不同以及z.constructor值的情况
is different from the Object.getPrototypeOf(z).constructor value?不同于Object.getPrototypeOf(z).constructor值?

I think it is just shortcut but I am not sure as I don't find我认为这只是捷径,但我不确定,因为我找不到
this stated explicitly in any authoritative source of doc.这在任何权威的文档来源中都明确说明。

EDIT : This code below shows that setting Object.getPrototypeOf(z).constructor implicitly sets the other value too.编辑:下面的代码显示设置Object.getPrototypeOf(z).constructor隐式设置其他值。 But setting z.constructor does not set the other value.但是设置z.constructor不会设置其他值。
So now I am puzzled... how is this implemented?所以现在我很困惑......这是如何实现的? Seems z.constructor is not just a shortcut but some sort of copy.似乎z.constructor不仅是快捷方式,而且是某种副本。 But if it's a copy why is it affected when we change/set the Object.getPrototypeOf(z).constructor to a new value?但是,如果它是副本,为什么当我们将Object.getPrototypeOf(z).constructor更改/设置为新值时它会受到影响?

    function Animal() {

        this.ttype = "Animal"

    }

    function Plant(){
        this.ttype = "Plant"
    }

    var p1 = new Plant();
    console.log(p1.constructor);
    console.log(p1.constructor === Object.getPrototypeOf(p1).constructor);
    p1.constructor = Animal;
    console.log(p1.constructor === Object.getPrototypeOf(p1).constructor);

    var p2 = new Plant();
    console.log(p2.constructor);
    console.log(p2.constructor === Object.getPrototypeOf(p2).constructor);
    Object.getPrototypeOf(p2).constructor = Animal;
    console.log(p2.constructor === Object.getPrototypeOf(p2).constructor);
    console.log(p2.constructor);

The constructor property of an object is normally inherited from it's prototype chain. object 的constructor属性通常继承自它的原型链。 There are two exceptions:有两个例外:

  1. Objects whose prototype chain doesn't contain any objects.原型链不包含任何对象的对象。 These be created using Object.create(null) and are useful for setting up look up tables that aren't affected by properties inherited from somewhere else.这些是使用Object.create(null)创建的,对于设置不受从其他地方继承的属性影响的查找表很有用。

  2. Objects that have been assigned a local "own" property called constructor , as in已分配了名为constructor的本地“自己”属性的对象,如

    myObject.constructor = 42;

    However, this is a technicality and not something you would expect to see in real code.但是,这是技术性问题,而不是您希望在实际代码中看到的内容。

So leaving these aside, where is constructor inherited from?那么抛开这些, constructor是从哪里继承的呢?

By language design, constructor is inherited from the constructor function's prototype property.通过语言设计, constructor函数继承自构造函数的prototype属性。 Every plain vanilla function in JavaScript is set up with a prototype property with a non enumerable property called constructor set to the function object itself. Every plain vanilla function in JavaScript is set up with a prototype property with a non enumerable property called constructor set to the function object itself. By this means any standard function can be called as a constructor without modification.通过这种方式,任何标准的 function 都可以作为构造函数调用而无需修改。 However the overhead is that standard functions never intended to be used as constructors have a prototype property anyway.然而,开销是标准函数从不打算用作构造函数,无论如何都具有prototype属性。

Now more complications:现在更复杂:

  1. The prototype property of a standard function object is writable.标准 function object 的prototype属性是可写的。 If it is updated to a new object value, objects constructed by the function will inherit constructor from the ammended prototype object - which would generally be different to the constructor value of the overwritten prototype value.如果将其更新为新的 object 值,则由 function 构造的对象将从修改后的prototype object 继承constructor函数 - 这通常与被覆盖的prototypeconstructor值不同。

  2. The constructor property of the prototype property of a function is not write protected. function 的prototype属性的constructor属性没有写保护。

    • In combination, these two factors allow setting up prototype chains of arbitrary length, simulating in part the extension of classes in a class based language.结合起来,这两个因素允许建立任意长度的原型链,部分模拟基于 class 的语言中的类扩展。 EG If C objects inherit from B which inherit from A you could write EG 如果C对象继承自B继承自A你可以写

      B.prototype = new A() // B objects inherit from an instance of A, // which inherits from A.prototype C.prototype = new B() // C objects inherit from an instance of B, // which inherits from B.prototype and A.prototype C.prototype.constructor = C; // C objects inherit C as their constructor.

These classic rules for chaining prototypes are quite lax: you can change the prototype property multiple times without affecting the inheritance chain of previously created objects.这些用于链接原型的经典规则非常宽松:您可以多次更改prototype属性而不会影响先前创建的对象的 inheritance 链。 However changing the prototype property of a constructor function multiple times has limited use (creating a polyfill for Object.create perhaps) and most unusual.但是,多次更改构造函数 function 的prototype属性的用途有限(可能为Object.create创建 polyfill)并且最不寻常。

Note the class keyword syntax to create constructor functions renders this kind of manipulation obsolete - you can't change a class constructor functions prototype property, and if you extend a "class" the prototype property of the extended class inherits from the base class's prototype property while having its constructor property set to the extended constructor, both automatically.请注意用于创建构造函数的class关键字语法使这种操作变得过时 - 您不能更改 class 构造函数prototype属性,如果您扩展“类”,则扩展 ZA2F2ED4F8EBC2CBB4C21A29DC40 的prototype属性继承自prototype属性 AB同时将其constructor属性设置为扩展构造函数,两者都是自动的。

Also note that arrow functions don't have a prototype property and cannot be used as constructors.另请注意,箭头函数没有prototype属性,不能用作构造函数。


q1 q1

Object.getPrototypeOf(z).constructor === z.constructor
Is this true for every object z in JavaScript?这对于 JavaScript 中的每个 object z 是否都是如此?

Yes, except for the exceptions listed under 1) and 2).可以,但 1) 和 2) 中列出的例外情况除外。

q2 q2

p1.constructor = Animal;

This creates an own property of p1 that shadows the inherited constructor property which can no longer be accessed (exception 2)这会创建一个自己的p1属性,它会隐藏无法再访问的继承的constructor属性(异常 2)

q3 q3

Object.getPrototypeOf(p2).constructor = Animal;

This line of code updates the constructor property of the object from where p2 inherits its constructor value from, so p2 's inherited constructor property is now Animal .这行代码更新了 object 的constructor属性, p2从其中继承了它的constructor值,因此p2的继承构造函数属性现在是Animal Other plant objects which similarly inherit from Plant.prototype would also see Animal as their constructor.类似地从Plant.prototype继承的其他植物对象也会将Animal视为它们的构造函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM