摘要:一是如何工作的在上是這樣描述的運算符用于測試構造函數的屬性是否出現在對象原型鏈中的任何位置換句話說,如果,那么必須是一個對象,而必須是一個合法的函數。下面我們舉一個例子一步步來說明第一步每一個構造函數都有一個屬性。
在 JavaScript 中,我們通常用 typeof 判斷類型,但是在判斷引用類型的值時,常常會遇到一個問題:無論引用的是什么類型的對象,都會返回 "object"(當然還有 "function") 。有時候我們需要知道這個引用對象的類型是數組還是一個包裝對象,這個時候 instanceof 就可以派上用場了。
廢話不多說,先來幾個例子熱身一下,全部都知道同學,請點擊右上角的關閉按鈕;模模糊糊的同學,可以繼續閱讀,只要掌握了原理,這些題目真的是易如反掌。
const a = "abc"; console.log(a instanceof String); // ? const b = new String("abc"); console.log(b instanceof String); // ?
console.log(String instanceof String); // ? console.log(Object instanceof Object); // ? console.log(Function instanceof Function); // ? console.log(Function instanceof Object); // ?一、instanceof 是如何工作的
在 MDN 上是這樣描述 instanceof 的:
instanceof 運算符用于測試構造函數的 prototype 屬性是否出現在對象原型鏈中的任何位置
換句話說,如果A instanceof B,那么 A 必須是一個對象,而 B 必須是一個合法的 JavaScript 函數。在這兩個條件都滿足的情況下:
判斷 B 的 prototype 屬性指向的原型對象(B.prototype)是否在對象 A 的原型鏈上。如果在,則為 true;如果不在,則為 false。
下面我們舉一個例子一步步來說明:
function Person() {} const p1 = new Person(); p1 instanceof Person; // true
第一步:每一個構造函數都有一個 prototype 屬性。
第二步:這個 prototype 屬性指向這個構造函數的原型對象
第三步:通過 new 關鍵字,可以創建一個構造函數的實例(這里是 p1),而實例上都有一個 __proto__ 屬性
第四步:實例上的 __proto__ 屬性也指向構造函數的原型對象,這樣我們就可以得到一張完整的關系圖了
第五步:p1 instanceof Person ,檢查 B(Person) 的 prototype 屬性指向的原型對象,是否在對象 A(p1) 的原型鏈上。
經過我們的一步步分解,發現 B(Person) 的 prototype 所指向的原型對象確實在 A(p1) 的原型鏈上,所以我們可以確定 p1 instanceof Person 一定是為 true 的。
我們再深入一點會發現,不僅僅 p1 instanceof Person 為 true ,p1 instanceof Object 也為 true ,這又是為什么呢?
其實,Person 的原型對象上也有一個 __proto__ 屬性,而這個屬性指向 Object 的 prototype 屬性所指向的原型對象,我們可以在控制臺打印一下:
既然有這個關系,那我們再完善一下上面的圖:
通過 Person 的例子,我們知道構造函數 Object 上的 prototype 屬性會指向它的原型對象:
現在,我們要判斷 p1 instanceof Object 的真假,還記得上面的定義么?我們再來一遍:
判斷 B 的 prototype 屬性指向的原型對象(B.prototype)是否在對象 A 的原型鏈上。如果在,則為 true;如果不在,則為 false。
此時,我們發現 B(Object) 的 prototype 屬性所指向的原型對象依然在 A(p1) 的原型鏈上,所以結果為 true 。
通過上面的例子我們可以知道,其實 instanceof 的原理非常簡單,就是一個查找原型鏈的過程,所以只要你理解了原型鏈的相關知識,理解 instanceof 的原理就不會再有問題了。這里我們稍微總結兩點與instanceof 有關的原型鏈知識:
所有 JavaScript 對象都有 __proto__ 屬性,只有 Object.prototype.__proto__ === null ;
構造函數的 prototype 屬性指向它的原型對象,而構造函數實例的 __proto__ 屬性也指向該原型對象;
二、如何實現一個 instanceof ?看了上面的過程,其實也很容易給出 instanceof 的實現方式:
function instance_of(left, right) { const RP = right.prototype; // 構造函數的原型 while(true) { if (left === null) { return false; } if (left === RP) { // 一定要嚴格比較 return true; } left = left.__proto__; // 沿著原型鏈重新賦值 } }
有了上面的實現方法,我們再解釋一下上面的例子:
function Person() {} const p1 = new Person(); p1 instanceof Object; // 用上面的代碼解釋它
第一次賦值
left = p1 right = Object RP = Object.prototype
第一次判斷
left !== null 并且 left !== RP ,繼續向上尋找 left 的原型鏈,準備新的賦值。
第二次賦值
left = p1.__proto__ = Person.prototype
第二次判斷
left !== null 并且 left !== RP ,繼續向上尋找 left 的原型鏈,準備新的賦值。
第三次賦值
left = p1.__proto__.__proto__ = Person.prototype.__proto__
第三次賦值
left !== null ,此時 left === RP ,返回 true ,函數執行完畢。
三、總結今天,我們用一個例子,通過畫圖以及代碼實現兩個角度剖析了 instanceof 的實現原理,其實思路也很簡單,無非就是一個沿原型鏈向上查找的過程。希望大家可以在以后的面試過程中,不再被" instanceof 的實現原理是什么?"這樣的面試難住了。
當然,閱讀永遠都只是一種十分被動的學習方法,我還是建議你能自己實踐一下。在文章的開頭有幾個例子,感興趣的同學可以挑選一個例子,自己通過畫圖以及代碼實現兩種方式再加深一遍理解,相信你會理解的更深刻。
如果文章中錯誤或表述不嚴謹的地方,歡迎指正。
最后,文章會首先發布在我的 Github ,以及公眾號上,歡迎關注。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/103544.html
摘要:寫在前面的話最近互聯網朋友圈充斥著一股恐慌的氣息。本人作為一名,萬不敢稱資深,只是呆過幾年大型央企和大型互聯網企業,聊有一點自己的看法罷了。如果不放心,以一周為期,對展示在面前的機會進行初步分級。也可以略高于期望,以此探一探對方的反應。 showImg(https://segmentfault.com/img/bVblxeY?w=1008&h=298); 寫在前面的話 最近互聯網朋...
摘要:雖然有了十全的計劃,但如何高效率去記住上面那么多東西是一個大問題,看看我是怎么做的。 前言 前一篇文章講述了我在三月份毫無準備就去面試的后果,一開始心態真的爆炸,但是又不服氣,一想到每次回來后家人朋友問我面試結果的期待臉,越覺得必須付出的行動來證明自己了。 面經傳送門:一個1年工作經驗的PHP程序員是如何被面試官虐的? 下面是我花費兩個星期做的準備,主要分三部分: 有計劃——計劃好...
摘要:拿到秋招的同學,如確定入職需與用人單位簽署三方協議,以保證雙方的利益不受損失。當然每個崗位所要求的側重點不同,但卻百變不離其宗。方法論要想達成某個目標都有其特定的方法論,學習技術也不例外,掌握適當的學習方法才能事半功倍。 寫在前面的話 筆者從17年的2月份開始準備春招,其中遇到不少坑,也意識到自己走過的彎路。故寫了這篇文章總結一番,本文適合主動學習的,對自己要學的課程不明確的,對面試有...
摘要:拿到秋招的同學,如確定入職需與用人單位簽署三方協議,以保證雙方的利益不受損失。當然每個崗位所要求的側重點不同,但卻百變不離其宗。方法論要想達成某個目標都有其特定的方法論,學習技術也不例外,掌握適當的學習方法才能事半功倍。 寫在前面的話 筆者從17年的2月份開始準備春招,其中遇到不少坑,也意識到自己走過的彎路。故寫了這篇文章總結一番,本文適合主動學習的,對自己要學的課程不明確的,對面試有...
摘要:所以要告訴她,等她回來后我指定比以前更愛她,我一直想告訴她,我比她想象中要更愛她。以后的生活就輕松很多。等到完成之后再回顧這一段路程的時候,你肯定會感慨良多。 她呀...
閱讀 1644·2023-04-26 02:11
閱讀 2985·2023-04-25 16:18
閱讀 3717·2021-09-06 15:00
閱讀 2636·2019-08-30 15:55
閱讀 1939·2019-08-30 13:20
閱讀 2056·2019-08-26 18:36
閱讀 3129·2019-08-26 11:40
閱讀 2546·2019-08-26 10:11