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

时间:2019-11-04 10:34:54

标签: javascript

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

JavaScript中的每个对象z都是这样吗?

我的意思是z.constructor只是一个捷径,使我们可以更轻松地检索
对象内部[[Prototype]]属性的构造方法属性。

或者...在某些情况下,两者和z.constructor值不同
Object.getPrototypeOf(z).constructor值不同吗?

我认为这只是捷径,但我不确定,因为我找不到
在任何权威文档中都明确指出了这一点。

编辑: 下面的代码显示设置Object.getPrototypeOf(z).constructor也隐式设置了另一个值。但是设置z.constructor不会设置其他值。
所以现在我感到困惑...如何实现?看来z.constructor不仅是捷径,而且还是某种复制品。但是,如果是副本,为什么在我们将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);

1 个答案:

答案 0 :(得分:1)

对象的constructor属性通常是从其原型链继承的。有两个例外:

  1. 其原型链不包含任何对象的对象。它们是使用Object.create(null)创建的,对于设置不受其他地方继承的属性影响的查找表很有用。

  2. 已被分配为constructor的本地“拥有”属性的对象,如

    myObject.constructor = 42;
    

    但是,这只是技术问题,而不是您希望在实际代码中看到的东西。

那么撇开这些,constructor是从哪里继承的?

通过语言设计,constructor继承自构造函数的prototype属性。 JavaScript中的每个普通香草函数都设置有一个prototype属性,并且将一个不可枚举的属性constructor设置为函数对象本身。通过这种方法,任何标准函数都可以作为构造函数调用而无需修改。但是,开销是,从不打算用作构造函数的标准函数始终具有prototype属性。

现在更多的并发症了:

  1. 标准函数对象的prototype属性是可写的。如果将其更新为新的对象值,则由该函数构造的对象将从继承的constructor对象继承prototype -通常与改写后的{{ 1}}值。

  2. 函数的constructor属性的prototype属性不受写保护。

    • 结合起来,这两个因素允许建立任意长度的原型链,部分模拟基于类语言的类扩展。如果constructor个对象继承自prototype的{​​{1}}个对象,您可以编写

      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. 创建一个polyfill),并且最不常见。

请注意,用于创建构造函数的prototype关键字语法使这种操作变得过时了-您不能更改类构造函数的prototype属性,如果扩展了“类”,则{{扩展类的1}}属性继承自基类的Object.create属性,而其class属性则自动设置为扩展构造函数。

还请注意,箭头函数没有prototype属性,因此不能用作构造函数。


q1

  

prototype
  JavaScript中的每个对象z都适用吗?

是,除了1)和2)中列出的例外。

q2

  

prototype

这将创建自己的属性constructor,该属性遮盖了无法再访问的继承的prototype属性(异常2)

q3

  

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

此行代码更新了对象p1.constructor = Animal;p1继承其constructor值的对象的属性,因此Object.getPrototypeOf(p2).constructor = Animal;的继承构造函数属性现在为{{ 1}}。同样从constructor继承的其他植物对象也将p2视为其构造函数。