91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

js原型鏈解析

發布時間:2020-07-28 12:06:42 來源:網絡 閱讀:2072 作者:夢想代碼 欄目:web開發

js原型鏈解析


大家可以先仔細分析下該圖,然后讓我們進入主題

prototype

首先來介紹下 prototype 屬性。這是一個顯式原型屬性,只有函數才擁有該屬性。基本上所有函數都有這個屬性,但是也有一個例外

let fun = Function.prototype.bind()

如果你以上述方法創建一個函數,那么可以發現這個函數是不具有 prototype 屬性的。

prototype 如何產生的

當我們聲明一個函數時,這個屬性就被自動創建了。

function Foo() {}

并且這個屬性的值是一個對象(也就是原型),只有一個屬性 constructor

js原型鏈解析

constructor 對應著構造函數,也就是 Foo

constructor

constructor 是一個公有且不可枚舉的屬性。一旦我們改變了函數的 prototype ,那么新對象就沒有這個屬性了(當然可以通過原型鏈取到 constructor)。

js原型鏈解析

那么你肯定也有一個疑問,這個屬性到底有什么用呢?其實這個屬性可以說是一個歷史遺留問題,在大部分情況下是沒用的,在我的理解里,我認為他有兩個作用:

  • 讓實例對象知道是什么函數構造了它

  • 如果想給某些類庫中的構造函數增加一些自定義的方法,就可以通過 xx.constructor.method 來擴展

_proto_

這是每個對象都有的隱式原型屬性,指向了創建該對象的構造函數的原型。其實這個屬性指向了 [[prototype]],但是 [[prototype]] 是內部屬性,我們并不能訪問到,所以使用 _proto_ 來訪問。

因為在 JS 中是沒有類的概念的,為了實現類似繼承的方式,通過 _proto_ 將對象和原型聯系起來組成原型鏈,得以讓對象可以訪問到不屬于自己的屬性。

實例對象的 _proto_ 如何產生的

從上圖可知,當我們使用 new 操作符時,生成的實例對象擁有了 _proto_屬性。

function Foo() {}// 這個函數是 Function 的實例對象// function 就是一個語法糖// 內部調用了 new Function(...)

所以可以說,在 new 的過程中,新對象被添加了 _proto_ 并且鏈接到構造函數的原型上。

new 的過程
  1. 新生成了一個對象

  2. 鏈接到原型

  3. 綁定 this

  4. 返回新對象

在調用 new 的過程中會發生以上四件事情,我們也可以試著來自己實現一個 new

function create() {    // 創建一個空的對象
    let obj = new Object()    // 獲得構造函數
    let Con = [].shift.call(arguments)    // 鏈接到原型
	obj.__proto__ = Con.prototype
    // 綁定 this,執行構造函數
    let result = Con.apply(obj, arguments)    // 確保 new 出來的是個對象
    return typeof result === 'object' ? result : obj
}

對于實例對象來說,都是通過 new 產生的,無論是 function Foo() 還是 let a = { b : 1 } 。

對于創建一個對象來說,更推薦使用字面量的方式創建對象。因為你使用 new Object() 的方式創建對象需要通過作用域鏈一層層找到 Object,但是你使用字面量的方式就沒這個問題。

function Foo() {}// function 就是個語法糖// 內部等同于 new Function()let a = { b: 1 }// 這個字面量內部也是使用了 new Object()

Function.proto === Function.prototype

對于對象來說,xx.__proto__.contrcutor 是該對象的構造函數,但是在圖中我們可以發現 Function.__proto__ === Function.prototype,難道這代表著 Function 自己產生了自己?

答案肯定是否認的,要說明這個問題我們先從 Object 說起。

從圖中我們可以發現,所有對象都可以通過原型鏈最終找到 Object.prototype ,雖然 Object.prototype也是一個對象,但是這個對象卻不是 Object 創造的,而是引擎自己創建了 Object.prototype 。所以可以這樣說,所有實例都是對象,但是對象不一定都是實例。

接下來我們來看 Function.prototype 這個特殊的對象,如果你在瀏覽器將這個對象打印出來,會發現這個對象其實是一個函數。

js原型鏈解析

我們知道函數都是通過 new Function() 生成的,難道 Function.prototype 也是通過 new Function()產生的嗎?答案也是否定的,這個函數也是引擎自己創建的。首先引擎創建了 Object.prototype ,然后創建了 Function.prototype ,并且通過 __proto__ 將兩者聯系了起來。這里也很好的解釋了上面的一個問題,為什么 let fun = Function.prototype.bind() 沒有 prototype 屬性。因為 Function.prototype是引擎創建出來的對象,引擎認為不需要給這個對象添加 prototype 屬性。

所以我們又可以得出一個結論,不是所有函數都是 new Function() 產生的。

有了 Function.prototype 以后才有了 function Function() ,然后其他的構造函數都是 function Function() 生成的。

現在可以來解釋 Function.__proto__ === Function.prototype 這個問題了。因為先有的 Function.prototype 以后才有的 function Function() ,所以也就不存在雞生蛋蛋生雞的悖論問題了。對于為什么 Function.__proto__ 會等于 Function.prototype ,個人的理解是:其他所有的構造函數都可以通過原型鏈找到 Function.prototype ,并且 function Function() 本質也是一個函數,為了不產生混亂就將 function Function() 的 __proto__ 聯系到了 Function.prototype 上。

總結

  • Object 是所有對象的爸爸,所有對象都可以通過 __proto__ 找到它

  • Function 是所有函數的爸爸,所有函數都可以通過 __proto__ 找到它

  • Function.prototype 和 Object.prototype 是兩個特殊的對象,他們由引擎來創建

  • 除了以上兩個特殊對象,其他對象都是通過構造器 new 出來的

  • 函數的 prototype 是一個對象,也就是原型

  • 對象的 __proto__ 指向原型, __proto__ 將對象和原型連接起來組成了原型鏈


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

徐闻县| 长沙县| 文成县| 咸宁市| 砚山县| 遂溪县| 兰坪| 鹤山市| 历史| 衡山县| 柯坪县| 新泰市| 常州市| 山丹县| 新密市| 巴楚县| 海晏县| 建昌县| 长岛县| 尼玛县| 措勤县| 台中县| 白沙| 西青区| 武川县| 卫辉市| 麻城市| 金乡县| 安乡县| 通州市| 宣化县| 龙陵县| 三台县| 利川市| 台北市| 汝州市| 麟游县| 常德市| 西宁市| 桦川县| 中牟县|