判斷一個物件是不是陣列,有幾種辦法?
這是一個出現過無數次的話題,這裡再次重寫僅作為個人的學習筆記,謝謝觀看。
0、typeof
typeof 運算子的主要作用就是用來檢測資料的型別,一般情況下我們都是使用它來判斷資料型別,但是這裡,我把typeof 放在0的位置,因為 typeof 不能檢測到陣列型別!typeof 所能識別的型別只有原始型別(Undefined,Null,Boolean,Number,String,Symbol )以及 function 和 object。
需要注意的是null,null所檢測出來的結果是”object”,因為在js中,null除了作為空引用的存在,它也是物件整個原型鏈上最頂端的存在,即
Object.prototype.__proto__ === null;//true
其他使用typeof的場景:
// Numbers
typeof 3.14 === 'number';
typeof Math.LN2 === 'number';
typeof Infinity === 'number';
typeof NaN === 'number'; //儘管NaN是"Not-A-Number"的縮寫
// Strings
typeof "bla" === 'string';
typeof (typeof 1) === 'string'; //typeof總是返回一個字串
// Booleans
typeof true === 'boolean';
// Symbols
typeof Symbol() === 'symbol';
typeof Symbol.iterator === 'symbol';
// Undefined
typeof undefined === 'undefined';
// null
typeof null === 'object';//從一開始出現JavaScript就是這樣的
// function
typeof function(){} === 'function';
typeof class C{} === 'function'
// Objects
typeof {a:1} === 'object';
// 下面的結果是什麼?
typeof new Boolean(true) === 'object';
typeof new Number(1) === 'object';
typeof new String("abc") === 'object';
//new 所建立的都是物件,賦值給變數是執行了內部valueOf()或者toString()函式
最後,typeof不能檢測到陣列型別!
1、驗證原型物件:
從原型鏈上尋找(認祖歸宗)
1、Object.getPrototypeOf(obj) == Array.prototype
getPrototypeOf: 這是Object自帶的一個API,作用是獲取一個物件的原型物件
2、var bool = Array.prototype.isPrototypeOf(obj)
每個物件都有一個isPrototypeOf的API,繼承自Object.prototype,用來 判斷father(Array)是否是child(obj)的父物件
2、驗證建構函式:
從建構函式上判斷(它的親孃)
1、obj.constructor == Array
建構函式的prototype指向原型物件,同時,原型物件有constructor指回建構函式物件,constructor只在原型物件上有
2、var bool = obj instanceof Array
instance: 判斷物件(obj)是否由建構函式(Array)創建出來
這種方法有一個問題,就是驗證不夠嚴格。 即使物件建立時不是使用陣列建立的,但是隻要原型鏈上有陣列型別,也認為是陣列,如下面一段程式碼:
function Test(){}
Test.prototype = Array.prototype;
let test = new Test();
test instanceof Array;//true
3、檢查內部屬性class + call或apply:
這個class不是es6中物件宣告的class
這個class是每個物件中記錄物件建立時使用的型別的屬性,一旦物件被建立,class屬性就無法被修改!
獲得class的唯一的辦法就是呼叫Object.prototype中的toString()方法
輸出結果有”[object Object]”,”[object Function]”等
問題: 幾乎所有內建物件的原型物件都重寫了Object中的toString方法,所有內建物件的子物件,都無法直接調到Object的toString。
let arr = [1];
arr.toString();//"1"
let date = new Date();
date.toString();//"Wed Mar 07 2018 16:22:16 GMT+0800 (中國標準時間)"
雖然直接使用不行,但是我們可以利用js的call和apply函式來解決這個問題
Object.prototype.toString.call(obj)=="[object Array]"
使用這個方法判斷其他型別:
console.log(Object.prototype.toString.call("jerry"));//[object String]
console.log(Object.prototype.toString.call(12));//[object Number]
console.log(Object.prototype.toString.call(true));//[object Boolean]
console.log(Object.prototype.toString.call(undefined));//[object Undefined]
console.log(Object.prototype.toString.call(null));//[object Null]
console.log(Object.prototype.toString.call({name: "jerry"}));//[object Object]
console.log(Object.prototype.toString.call(function(){}));//[object Function]
console.log(Object.prototype.toString.call([]));//[object Array]
console.log(Object.prototype.toString.call(new Date));//[object Date]
console.log(Object.prototype.toString.call(/\d/));//[object RegExp]
function Person(){};
console.log(Object.prototype.toString.call(new Person));//[object Object]
4、ES5中的API:Array.isArray(obj)
這是ES5出的一個API,專門用來判斷一個物件是不是陣列的,所以,看到這裡有沒有感覺前面都白看了….
他的用法也很簡單:
var arr = [1,2,3,4];
Array.isArray(arr);//true
寫在最後
如果文中有什麼錯誤的地方,還請大家給予指出,另外大家如果還有什麼別的方法的話,也可以在評論區寫下或私信我,大家集思廣益,相互學習,共同進步。