1. 程式人生 > >判斷一個物件是不是陣列,有幾種辦法?

判斷一個物件是不是陣列,有幾種辦法?

這是一個出現過無數次的話題,這裡再次重寫僅作為個人的學習筆記,謝謝觀看。

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

寫在最後

如果文中有什麼錯誤的地方,還請大家給予指出,另外大家如果還有什麼別的方法的話,也可以在評論區寫下或私信我,大家集思廣益,相互學習,共同進步。