深度解析原型中的各個難點

2021-09-11 22:01:45 字數 3535 閱讀 4008

本文同步分布在我的 github 上

本文不會過多介紹基礎知識,而是把重點放在原型的各個難點上。

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

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

let fun = function.prototype.bind()

複製**

如果你以上述方法建立乙個函式,那麼可以發現這個函式是不具有prototype屬性的。

prototype 如何產生的

當我們宣告乙個函式時,這個屬性就被自動建立了。

function

foo() {}

複製**

並且這個屬性的值是乙個物件(也就是原型),只有乙個屬性constructor

constructor對應著建構函式,也就是foo

constructor

constructor是乙個公有且不可列舉的屬性。一旦我們改變了函式的prototype,那麼新物件就沒有這個屬性了(當然可以通過原型鏈取到constructor)。

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

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

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

例項物件的_proto_如何產生的

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

function

foo() {}

// 這個函式是 function 的例項物件

// function 就是乙個語法糖

// 內部呼叫了 new function(...)

複製**

所以可以說,在new的過程中,新物件被新增了_proto_並且鏈結到建構函式的原型上。

new 的過程

新生成了乙個物件

鏈結到原型

繫結 this

返回新物件

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

function

create()

複製**

對於例項物件來說,都是通過new產生的,無論是function foo()還是let a =

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

function

foo() {}

// function 就是個語法糖

// 內部等同於 new function()

let a =

// 這個字面量內部也是使用了 new object()

複製**

對於物件來說,xx.__proto__.contrcutor是該物件的建構函式,但是在圖中我們可以發現function.__proto__ === function.prototype,難道這代表著function自己產生了自己?

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

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

接下來我們來看function.prototype這個特殊的物件,如果你在瀏覽器將這個物件列印出來,會發現這個物件其實是乙個函式。

我們知道函式都是通過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上。

深度解析原型中的各個難點

本文不會過多介紹基礎知識,而是把重點放在原型的各個難點上。大家可以先仔細分析下該圖,然後讓我們進入主題 首先來介紹下prototype屬性。這是乙個顯式原型屬性,只有函式才擁有該屬性。基本上所有函式都有這個屬性,但是也有乙個例外 let fun function.prototype.bind 如果你...

深度解析原型中的各個難點

首先來介紹下 prototype 屬性。這是乙個顯式原型屬性,只有函式才擁有該屬性。基本上所有函式都有這個屬性,但是也有乙個例外 let fun function.prototype.bind 如果你以上述方法建立乙個函式,那麼可以發現這個函式是不具有 prototype 屬性的。prototype...

JS原型和原型鏈深度解析

說完閉包,我想原型和原型鏈是js中的難點也是重點,明白了原型和原型鏈會讓我們在後面不管是學習還是工作都會更加高效,並且原型和原型鏈會是面試中必不可少的話題 任何物件都有乙個原型物件,這個原型物件由物件的內建屬性 proto 指向它的建構函式的prototype指向的物件,即任何物件都是由乙個建構函式...