如果我們在 chrome 控制臺中創建一個陣列,
arr=[1,2];
并使用 chrome devtools 檢查原型鏈arr.__proto__.__proto__,我們得到以下結果。

如您所見,該__proto__物件指向 null,這是我在邏輯上所期望的。但是當我嘗試訪問原型鏈的同一級別,即Object.Prototype,使用arr.__proto__,然后搜索下拉選單時,我得到了以下結果。

正如您在突出顯示的行中看到的那樣,這一次__proto__是指向另一個Object.Prototype. 在進一步打開它時,我得到了與上一個命令相同的內容(檢查上一張圖片)。
有人可以告訴我這個額外的層是如何Object.prototype在某些命令中創建的,而在其他命令中卻沒有?
PS 我只是在學習原型繼承,這是我試圖了解它是如何在 JS 環境中實作的。
uj5u.com熱心網友回復:
這是由于 Chrome 開發工具中的一種奇怪行為。(現已棄用)__proto__屬性是一個 getter/accessor 屬性,這意味著當它被訪問時,它會運行一部分代碼。那部分代碼看起來像這樣:
Object.getPrototypeOf(this); // which returns this[[Prototype]]
上面示例中的this通常是您呼叫的物件.__proto__。例如,如果你做了arr.__proto__,那么this就是arr,所以我們最終得到了arr預期的陣列原型。在 Chrome 開發工具控制臺中,情況有些不同。而不是在像這樣的物件上呼叫getter arr,而是在您按下時手動呼叫它(...):

所以現在的問題是 -當在 Chrome 開發工具中手動呼叫 getter 而不是通過屬性訪問呼叫它時,在 getter 內部this執行時的價值是什么?這由 Chrome 開發工具團隊決定,但它的行為方式似乎是將 設定為最初記錄的物件1。在您的第二個示例中,該物件是. 結果,getter 最終再次顯示 的原型,而不是.Object.getPrototypeOf(this);__proto__arr.__proto__thisarr.__proto__arr.__proto__null
下面的代碼片段(參見 Chrome 控制臺輸出)是此行為的一個簡單示例:
const obj = Object.create({
get nested() {
console.log("obj === this:", this === obj); // true
console.log("obj[[Prototype]] === this:", this === Object.getPrototypeOf(obj)); // false
return this;
}
}, {
foo: {
value: 'bar',
enumerable: true
}
});
// View chrome console for output
console.log(obj);
在上面的示例中,使用屬性創建了一個新物件,該屬性{foo: "bar"}的原型設定為一個名為 的物件nested() {}。此 getter 回傳并記錄 的值this。當上述代碼在 Chrome 中運行時,通過單擊 (ie: ) 屬性呼叫 getter (...),obj[[Prototype]]您obj.__proto__將nested獲得以下輸出:

在上面,兩個紅框代表同一個物件,表明當使用 呼叫它時this,getter 內部并不參考原型物件(即:) ,而是參考最初記錄的物件。與此不同的是,當您使用 時,記錄的物件是,因此當您呼叫getter 時,參考該物件,當訪問其原型時回傳。{nested: (...)}(...)arr.__proto__.__proto__Object.prototype__proto__thisObject.prototypenull
要正確遍歷原型鏈,您可以使用嵌套呼叫Object.getPrototypeOf():
Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(arr))); // null
1這只是基于一些觀察的假設,但可能不正確 - 我不完全確定 chrome 如何決定將其設定this為,但需要注意的重要一點是,它并不總是getter 屬性出現在。
uj5u.com熱心網友回復:
你arr.__proto__指的是Array.prototype,一個理想的規則陣列。當您再次添加 a__proto__時,這指的是根物件 aka Object.prototype。現在是最花哨的部分。Object.__proto__.__proto__兩者Object.prototype都是平等的。所以,你可以再次得到__proto__它!
console.log(arr.__proto__ === Array.prototype) // true
console.log(Array.prototype.__proto__ === Object.__proto__.__proto__) // true
console.log(Object.__proto__.__proto__ === Object.prototype) // true
但如果你直接要求arr.__proto__.__proto__.__proto__,它將為空。由于上述原因,您可以間接訪問它,但您不能直接訪問它。記住Object.__proto__是 null 但Object.__proto__.__proto__不是。又來了Object.prototype!
console.log(Object.__proto__.__proto__) // Root Object(Object.prototype)
console.log(Object.__proto__) // null
console.log(arr.__proto__.__proto__.__proto__) // null
在代碼編輯器上測驗(Android v8.1)
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/459963.html
標籤:javascript 遗产 谷歌浏览器开发工具 原型 原型继承
