簡體   English   中英

JavaScript obj.constructor vs obj.[[Prototype]] 的構造函數

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

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

這對於 JavaScript 中的每個 object 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);

object 的constructor屬性通常繼承自它的原型鏈。 有兩個例外:

  1. 原型鏈不包含任何對象的對象。 這些是使用Object.create(null)創建的,對於設置不受從其他地方繼承的屬性影響的查找表很有用。

  2. 已分配了名為constructor的本地“自己”屬性的對象,如

    myObject.constructor = 42;

    但是,這是技術性問題,而不是您希望在實際代碼中看到的內容。

那么拋開這些, constructor是從哪里繼承的呢?

通過語言設計, 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. 通過這種方式,任何標准的 function 都可以作為構造函數調用而無需修改。 然而,開銷是標准函數從不打算用作構造函數,無論如何都具有prototype屬性。

現在更復雜:

  1. 標准 function object 的prototype屬性是可寫的。 如果將其更新為新的 object 值,則由 function 構造的對象將從修改后的prototype object 繼承constructor函數 - 這通常與被覆蓋的prototypeconstructor值不同。

  2. function 的prototype屬性的constructor屬性沒有寫保護。

    • 結合起來,這兩個因素允許建立任意長度的原型鏈,部分模擬基於 class 的語言中的類擴展。 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.

這些用於鏈接原型的經典規則非常寬松:您可以多次更改prototype屬性而不會影響先前創建的對象的 inheritance 鏈。 但是,多次更改構造函數 function 的prototype屬性的用途有限(可能為Object.create創建 polyfill)並且最不尋常。

請注意用於創建構造函數的class關鍵字語法使這種操作變得過時 - 您不能更改 class 構造函數prototype屬性,如果您擴展“類”,則擴展 ZA2F2ED4F8EBC2CBB4C21A29DC40 的prototype屬性繼承自prototype屬性 AB同時將其constructor屬性設置為擴展構造函數,兩者都是自動的。

另請注意,箭頭函數沒有prototype屬性,不能用作構造函數。


q1

Object.getPrototypeOf(z).constructor === z.constructor
這對於 JavaScript 中的每個 object z 是否都是如此?

可以,但 1) 和 2) 中列出的例外情況除外。

q2

p1.constructor = Animal;

這會創建一個自己的p1屬性,它會隱藏無法再訪問的繼承的constructor屬性(異常 2)

q3

Object.getPrototypeOf(p2).constructor = Animal;

這行代碼更新了 object 的constructor屬性, p2從其中繼承了它的constructor值,因此p2的繼承構造函數屬性現在是Animal 類似地從Plant.prototype繼承的其他植物對象也會將Animal視為它們的構造函數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM