JS開發者應懂的33個概念系列5(下)--typeof 與 instanceof && 23--原型繼承與原型鏈

Wendydesigner發表於2019-01-10

JS開發者應懂的33個概念系列5(下)--typeof 與 instanceof && 23--原型繼承與原型鏈

typeof的原理

typeof可以用來判斷原始值的型別,以及區分物件值和原始值.我們可以利用 typeof 來判斷number, string, object, boolean, function, undefined, symbol 這七種型別。

一個 js 的變數,在它的底層實現中, 型別資訊是怎麼實現的呢?也就是說js 在底層是怎麼儲存資料的型別資訊呢?typeof也就是通過型別資訊進行判斷的。

js 在底層儲存變數的時候,會在變數的機器碼的低位1-3位儲存其型別資訊:

  • 000 object
  • 010 浮點數
  • 100 string
  • 110 boolean
  • 1 整數

對於 undefinednull 來說,這兩個值的資訊儲存是有點特殊的。

  • null:所有機器碼均為0
  • undefined:用 −2^30 整數來表示

所以,typeof在判斷 null的時候就出現問題了,由於 null 的所有機器碼均為0,因此直接被當做了物件來看待。所以,在判斷變數型別的時候,避免對null進行判斷。

typeof null   // "object"
複製程式碼

instanceof的原理

在 JavaScript 中,判斷一個變數的型別嚐嚐會用 typeof 運算子,在使用 typeof 運算子時採用引用型別儲存值會出現一個問題,無論引用的是什麼型別的物件,它都返回 "object"

直接上硬貨:

function instance_of(L, R) {//L 表示左表示式,R 表示右表示式
 var O = R.prototype;// 取 R 的顯示原型
 L = L.__proto__;// 取 L 的隱式原型
 while (true) { 
   if (L === null) 
     return false; 
   if (O === L)// 這裡重點:當 O 嚴格等於 L 時,返回 true 
     return true; 
   L = L.__proto__; 
 } 
}
複製程式碼

instanceof 在查詢的過程中會遍歷左邊變數原型鏈,直到找到右邊變數的 prototype,如果查詢失敗,則會返回 false,告訴我們左邊變數並非是右邊變數的例項。

劃重點,原型鏈

原型鏈

function Person() {}
var Student = new Person()
複製程式碼

JS開發者應懂的33個概念系列5(下)--typeof 與 instanceof && 23--原型繼承與原型鏈
先不著急解釋原型鏈,先看一下什麼是原型?

原型

  • 每一個建構函式都擁有一個prototype屬性,這個屬性指向一個物件,也就是原型物件。比如:建構函式Personprototype便是指向Person.prototype物件。
  • 原型物件預設擁有一個constructor屬性,指向它的那個建構函式(也就是說建構函式和原型物件是互相指向的關係)。比如:Person.prototype.constructor指向Person
  • 每個物件型別比如(Student,Person.prototype,Function.prototype)都擁有一個隱藏的屬性[[prototype]],指向它的原型物件,這個屬性可以通過 Object.getPrototypeOf(obj)obj.__proto__來訪問。
  • 實際上,建構函式的prototype屬性與它建立的例項物件的[[prototype]]屬性指向的是同一個物件,即Student.__proto__ === Person.prototype

JavaScript中,所有的物件都是由它的原型物件繼承而來,反之,所有的物件都可以作為原型物件存在。

訪問物件的屬性時,JavaScript會首先在物件自身的屬性內查詢,若沒有找到,則會跳轉到該物件的原型物件中查詢,也就是通過__proto__進行查詢。

所以呢,原型鏈就是你查詢過程所經歷的地方。

最後來個例子:

console.log(Object instanceof Object);//true 
console.log(Function instanceof Function);//true 
console.log(Function instanceof Object);//true 
 
複製程式碼

在複習一遍:

Object instanceof Object?

var O = Object.prototype;
var L = Object.__proto__; // L是Function.prototype
while(true) // 進入迴圈
L = Object.__proto__.__proto__ // L是Object.prototype
while(true) // 重新進入迴圈
O === L 
return true複製程式碼

總結口訣

  • Object.__proto__ === Function.prototype其中Object是建構函式
  • 指向Function.prototype是建構函式的__proto__屬性
  • 指向Object.prototype是原型物件的__proto__屬性
  • Object.prototype.__proto__null
  • *.prototype.constructor指向它的建構函式*
  • Object.prototype除了constructor__proto__外,還有toString(),valueOf()等屬性,下屬原型物件可以通過原型鏈繼承這些屬性。

JS開發者應懂的33個概念系列5(下)--typeof 與 instanceof && 23--原型繼承與原型鏈

相關文章