最近在做 Code Review 的時候,發現了一些小問題,查出結果之後發現竟然是因為 typeof 和 instanceof 引發的。
這屬於 JS 的基礎知識,正是由於太基礎了,所以很容易被忽略,導致項目中隨處可見的濫用。
為了鞏固基礎,我會通過實例來詳細說明,讓我們一起搞懂 typeof 和 instanceof。
一、typeof
typeof 其實就是判斷參數是什麼類型的實例,就一個參數,用例:typeof A
返回值:
"number"、"string"、"boolean"、"object"、"function" 和 "undefined"
我們先來驗證幾個基本類型:
這裡可以擴展一下,假如我們要判斷某個變量是否存在:
這時候,控制檯會報錯:
Uncaught ReferenceError: a is not defined
所以我們可以使用 typeof 來判斷:
這樣,就能避免代碼異常,是一種比較嚴謹的處理方式。
需要注意:ES6 中 let 和 const 會形成“暫時性死區”也意味著 typeof 不再是一個百分之百安全的操作。
typeof x; // ReferenceError
let x;
上面代碼中,變量x使用let命令聲明,所以在聲明之前,都屬於x的“死區”,只要用到該變量就會報錯。因此,typeof運行時就會拋出一個ReferenceError。
如果用 typeof 來判斷引用類型,會有怎樣的結果?
如上所示,引用類型的數據,都返回了 object,我們無法做到精確判斷。我們來總結一下:
1.對於基本類型,除 null 以外,均可以返回正確的結果。
2.對於引用類型,除 function 以外,一律返回 object 類型。
3.對於 null ,返回 object 類型。
4.對於 function 返回 function 類型。
這就需要用到 instanceof 來檢測某個對象是不是另一個對象的實例。
二、instanceof
instanceof 是用來判斷 A 是否為 B 的實例,表達式為:A instanceof B,如果 A 是 B 的實例,則返回 true,否則返回 false。
示例來自於:
https://blog.csdn.net/liwenfei123/article/details/77978027
從上述過程可以看出,當 A 的 __proto__ 指向 B 的 prototype 時,就認為 A 就是 B 的實例,我們來看幾個例子:
JS 中萬物皆對象的思想:
再舉個例子,我們通過一個簡單的繼承來說明:
很簡單,我們只需要理解下面這行代碼就可以了:
三、擴展
我們來分析一下 [ ]、Array、Object 三者之間的關係:
從 instanceof 能夠判斷出 [ ].proto 指向 Array.prototype,而 Array.prototype.proto 又指向了Object.prototype,最終 Object.prototype.proto 指向了null,標誌著原型鏈的結束。
因此,[]、Array、Object 就在內部形成了一條原型鏈:
依次類推,類似的 new Date()、new Person() 也會形成一條對應的原型鏈 。
instanceof 只能用來判斷兩個對象是否屬於實例關係, 而不能判斷一個對象實例具體屬於哪種類型。
四、鞏固知識
Question 1:下面如何輸出
答:function, true, true
Question2:如何判斷一個變量是否為數組?
答:通過 instanceof 判斷,或者 isArray 來判斷。
Question3:下面函數輸出結果是什麼?
答:這裡需要注意變量聲明提升,所以上面代碼等效於:
這時候,typeof name 就等於 undefined,所以輸出結果為 Hi~Jartto。
五、總結
突然發現我們總是忙碌於寫業務,卻忽略了基礎的重要性。所以在不斷寫 Bug 和解決 Bug 的路上越走越遠,卻徒勞無獲。
既然如此,那麼我們就從當下開始,打好根基。我會陸續更新更多 JS 基礎相關知識,大家共同學習。
1.
2.
3.
閱讀更多 F2EAwesome 的文章