一.速識概念:
?原型鏈可謂是面試頻考,所以今天帶大家快速了解下JavaScript的原型鏈機制🚀,說之前,先明確下面基本的概念(名稱與從屬關系),這是很重要的:
| 名稱 | 從屬關系 |
|---|---|
| prototype | 通常我們稱之為原型,它是函式的一個屬性,它是一個物件, |
| _ _ proto_ _ | 相當于一個連接點,它是物件的一個屬性,它也是一個物件, |
二. 原型鏈機制(建議跟著步驟敲代碼):
??其次,我們要知道的第一個點是,物件的 __ proto __ 保存著該物件建構式的prototype,這是什么意思?莫急,看下面這個例子你就懂了,
1.首先定義一個建構式:
function Test(){}
2.列印看它這個函式有沒有 prototype屬性:
console.log(Test.prototype);
3.確實有,看得出是一個物件:

4.new一個Test函式,將得到一個物件實體:
const test = new Test();
5.列印看這個物件有沒有 __ proto__ 這個屬性:
console.log(test.__proto__);
6.確實有,可以看到也是一個物件:

7.不知道你們發現沒有,上面兩次列印輸出的東西是一樣的,現在回到我剛開始提到的第一個知識點,物件的 __ proto __ 保存著該物件建構式的prototype,判斷看是不是真的:
console.log(Test.prototype === test.__proto__);
8.看結果,他們兩個果然是相等的,那現在明確了物件的 __ proto __ 保存著該物件建構式的prototype:

9.既然物件里會有 __ proto __屬性,而prototype也是一個物件,理所應當它也應該有 __ proto __屬性,輸出看看:
console.log(Test.prototype.__proto__);
10.確實存在著,發現還是一個物件:

11. 我們知道我們自己定義的物件其實都是 new Object 來的,輸出Object它的prototype看看:
console.log(Object.prototype);
12.我們發現,它和Test.prototype.__proto__好像是一樣的:

13.判斷一下,發現回傳的是ture,證明他們果然是一樣的:
console.log(Object.prototype === Test.prototype.__proto__);

14. 那現在我們知道了以下:test里有一個__proto__屬性和Test的prototype屬性相等,Test的prototype屬性里的__proto__和Object.prototype相等,那Object里的prototype屬性還有__proto__屬性嗎?如下所示,回傳null,確實是沒有了,Object就是走到頭了,
console.log(Object.prototype.__proto__);

?按照上面結果,我們可以得到下面結論:原型鏈就是一個以物件為基準,這個物件通過__proto__這個屬性為連接點找到了它的建構式的prototype,而這個prototype也是一個物件,它也有__proto__屬性,它也以這個為連接點找到了Obje.prototype,而Object的prototype不存在__proto__屬性了,所以鏈條到此為止,
?當然上面只是最簡單的原型鏈,很多情況會復雜許多,只需要知道一個物件可以通過__proto__屬性為連接點,一直連連連,一直連到Obje.prototype為止,
15.現在我給建構式定義一個a,輸出test發現是存在的:
function Test() {
this.a = 1;
}
const test = new Test();
console.log(test);

16.現在我通過Test.prototype屬性里定義一個b,輸出test發現b也是存在的,不過它存在test的__proto__里:
function Test() {
this.a = 1;
}
Test.prototype.b = 2;
const test = new Test();
console.log(test);

17.現在我通過Object.prototype屬性里定義一個c,輸出test發現c竟然也是存在的,不過它存在test的__proto__里的__proto__里,相當于存在Test的prototype屬性里的__proto__里,通過前面我們也證明了它確實是等于Object.prototype:
function Test() {
this.a = 1;
}
Test.prototype.b = 2;
Object.prototype.c = 3;
const test = new Test();
console.log(test);

?明明我不是在test里定義的a,b,c,但是都可以從test得到,其實這就是原型鏈繼承機制,
?通過這個物件的__proto__屬性為連接點往上找,而這個__ proto __ 保存著該物件建構式的prototype,這里找到了該物件建構式prototype,而prototype是物件,同樣也存在__proto__屬性,繼續往上找,一直找到Object的prototype,因為Object的prototype不存在__proto__屬性,所以一直到Object.prototype便終止,此時a,b,c都在鏈條上找到了,
18.比如我在Test里也直接定義了c是666,在Object.prototype也定義了c是3,那 test.c 是多少?會是通過原型鏈上第一次找到的回傳,先找到的是Test里的c,所以回傳666:
function Test() {
this.a = 1;
this.c = 666;
}
Test.prototype.b = 2;
Object.prototype.c = 3;
const test = new Test();
console.log(test);

三.擴展:
1.首先,我們知道我們定義的Test建構式其實是這樣生成的:
const Test = new Function();
這樣一來,不是會有如下關系么:
Test.__proto__ === Function.prototype
輸出發現,真的存在:
console.log(Test.__proto__ === Function.prototype);

既然如此,那么Function.__proto__往上找的話會是什么,結果是沒有了,JavaScript底層給我們規定了如下規則:
Function.__proto__ === Function.prototype
2.如果有一個物件:
const obj = {}
它實際是這樣來的:
const obj = new Object()
這樣一來,豈不是說 Object 是一個建構式,是一個函式?Object 是一個函式?試試看:
console.log(typeof Object)

確實型別是函式,這樣的話豈不是有:
Object.__proto__ === Function.prototype
輸出看看:
console.log(Object.__proto__ === Function.prototype)

確實成立,這樣一來,便存在以下關系:
Object.__proto__ === Function.__proto__
3.我們可以通過 hasOwnProperty()方法判斷一個物件是否存在有此屬性,且該屬性不是在原型鏈上繼承的,如下:
Test.prototype.b = 2;
Object.prototype.c = 3;
const test = new Test();
console.log(test.hasOwnProperty("a"));
console.log(test.hasOwnProperty("b"));
console.log(test.hasOwnProperty("c"));

當然相對的,可以用 in 來判斷一個物件是否存在有此屬性,且該屬性可以是在原型鏈上找到繼承的:
function Test() {
this.a = 1;
}
Test.prototype.b = 2;
Object.prototype.c = 3;
const test = new Test();
console.log("a" in test);
console.log("b" in test);
console.log("c" in test);

四. 結尾:
原型鏈介紹到這里就差不多啦,由于我才疏學淺,所以如果有錯誤的地方懇請大佬指出~🌈🌈🌈
下次再見啦~

其它文章:
~關注我看更多簡單創意特效:
文字煙霧效果 html+css+js
環繞倒影加載特效 html+css
氣泡浮動背景特效 html+css
簡約時鐘特效 html+css+js
賽博朋克風格按鈕 html+css
仿網易云官網輪播圖 html+css+js
水波加載影片 html+css
導航欄滾動漸變效果 html+css+js
書本翻頁 html+css
3D立體相冊 html+css
霓虹燈繪畫板效果 html+css+js
記一些css屬性總結(一)
Sass總結筆記
…等等
進我主頁看更多~
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/292519.html
標籤:其他
下一篇:jQuery全選案例
