js - 【陣列】怎麼判斷一個變數是陣列型別的?
怎麼判斷一個數組是陣列呢?
其實這個也是一個常考的題目。依稀記得我為數不多的面試經過中都被問道過。
方案一: instanceof
variable instanceof Array
解決思路:
使用型別判斷所給的方法 instanceof 進行判斷。
此方法返回一個布林值,能夠精確判斷一個物件的型別。
方案二:原型prototype + toString + call
Object.prototype.toString.call(variable).indexOf('Array') !== -1;
因為用了toString方法, 返回值是一個字串,還需要第二層判斷,看字串中是否有‘Array’這個關鍵字:
這個字串中有Array關鍵字的返回了數字8(就是Array這個字元在整個"[object Array]"中出現的下標數)。
如果變數物件不是一個純陣列,那麼返回的數字就是-1。因為indexOf方法在字串中找不到指定字元就會返回-1.
所以最後還需要通過比對數值是否等於-1就能判斷是否是陣列型別:
true就是了。
這裡可能難以理解的是call方法,畢竟前邊toString他們都各司其職。
首先我們打印出來物件原型上的toString方法返回什麼:
這裡涉及到Object.prototype.toString()的原理。由於我還學的不深入,就不做總結了,
具體可以看這篇總結的不錯:【傳送門】
大致意思有:
呼叫toString時會將this物件的[[class]]屬性值拿到,而這個屬性值就是該物件的真實型別。
[[class]]:一個內部屬性,字串值,表示物件的型別。只有toString這一個方法可以拿到。
而在es5中,toString獲取[[class]]值時需要經過這幾個比較特殊的步驟:
總結:
呼叫toString時會將this物件的[[class]]屬性值拿到,而這個屬性值就是該物件的真實型別。
又因為call能夠顯示的修改this指標的物件,所以用call將Object內部的this物件指向我們要檢測的變數自身。
從而再通過toString拿到變數的[[class]]值。
方案三:原型prototype + isPrototypeOf()方法
Array.prototype.isPrototypeOf(variable)
isPrototypeOf() 函式 : 用於指示物件是否存在於一個物件的原型鏈中。如果存在返回true,反之返回false。該方法屬Object物件,由於所有的物件都繼承了Object的物件例項,因此幾乎所有的例項物件都可以使用該方法。
所以在上邊程式碼公式中,如果variable的原型鏈中存在Array物件,就會返回true,也就說明variable是陣列型別。
isPrototypeOf的字面意思也就是a是不是b的原型。
看上圖就知道了,Array就是變數m的原型。所以用這個方法就能判斷出來。
對比一個型別為“純”Object的變數打印出來的資訊:
就更加一目瞭然為什麼用這個方法就可以判斷出來了吧!
方案四:建構函式 constructor
variable.constructor.toString().indexOf("Array") !== -1
這個一圖勝千言:
對比變數a的列印資訊,可以看出來,一個數組型別的例項,其原型__proto__.constructor右邊是Array關鍵字。
所以我們可以用這個關鍵點拿到也給字串:
然後用方案二的原理差不多的,我們查詢字串中Array關鍵字的位置是否等於-1。即能得出變數是否為陣列型別得了。
方案五:陣列方法 isArray()
Array.isArray(variable);
思路:
js的一個方法,專門用來測試物件是否是Array型別
在方案一、二、三的基礎上,可以總結整理這個isArray的內部原理
然後把方案1234自己封裝成isArray()函式。(待做)
2018-11-19 21:06:57