文章目錄
- 一、typeof方法
- 二、Instanceof與constructor屬性
- 1.Instanceof
- 2.constructor屬性
- 注意
- 三、Object.prototype.toString.call()方法
- 四、Array.isArray()
- 總結
一、typeof方法
當涉及到檢測資料的問題時,我們首先想到的可能就是用typeof來檢測資料型別,
其中typeof回傳示例如下:
// 數值
typeof 23 === 'number';
// 字串
typeof '' === 'string';
// 布林值
typeof false === 'boolean';
// Symbols
typeof Symbol() === 'symbol';
// Undefined
typeof undefined === 'undefined';
// 物件
typeof { a: 1 } === 'object';
typeof [1, 2, 4] === 'object';
// 函式
typeof function () { } === 'function';
//注意:
// 下面的例子令人迷惑,非常危險,沒有用處,避免使用它們,
typeof new Boolean(true) === 'object';
typeof new Number(1) === 'object';
typeof new String('abc') === 'object';
由上例我們可以看出,對于Function, String, Number, Undefined等這幾種基本型別來說,我們可以采用typeof檢測,
但是對于陣列或者正則(由一個字符序列形成的搜索模式)來說,typeof檢測無法滿足,因為兩者的回傳型別都是物件object,所以我們還需另找方法…
二、Instanceof與constructor屬性
1.Instanceof
instanceof可以判斷一個建構式的prototype屬性所指向的物件是否存在另外一個要檢測物件的原型鏈上,所以用來檢測某物件是否是陣列可能更好不過了,直接通過看回傳值true與false直接可以判斷是否是陣列,
代碼如下(示例):
console.log([] instanceof Array); // true
console.log({ a: 1 }instanceof Array); // false
2.constructor屬性
同樣 由于js中每一個物件都有一個constructor屬性,它參考了初始化該物件的建構式,比如判斷未知物件的型別,
代碼如下(示例):
//方法重寫
function isArray(obj) {
return typeof obj == 'object' && obj.constructor == Array
}
// 測驗de
console.log(isArray([])); // true
var a = {"a":1};
console.log(isArray(a)); // false
var b = [1,2,3];
console.log(isArray(b)); // true
console.log(isArray(/\d+/g)); // false
如上可以看到,通過呼叫prototype屬性與isArray 方法一般情況下可以判斷是否為陣列的列子
注意
但是這種一般情況真的可以完全判斷嗎?答案當然是否定的,當對于跨框架iframe的時候使用頁面中的陣列時:
代碼如下(示例):
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
xArray = window.frames[window.frames.length-1].Array;
var arr = new xArray("1","2","3","4","5");
//這個寫法IE下是不支持的,標準瀏覽器firefox,chrome下有
console.log(arr); // 列印出 ["1", "2", "3", "4", "5"]
console.log(arr instanceof Array); // false
console.log(arr.constructor === Array); // false
失敗的關鍵在于iframe元素的跨平臺的特點,使其有一套自己的執行環境,創建的陣列無法共享其prototype屬性,由于無法共享原型鏈,所以無法采用如上兩種方式判斷,
三、Object.prototype.toString.call()方法
以上三種方法都無法準確判斷物件是否為陣列,有沒有比較準確的方法呢,答案當然是肯定的,
function isArray(obj) {
return Object.prototype.toString.call(obj) == '[object Array]'; //call是用來改變指向的
} //方法重寫
// 代碼呼叫
//一般情況
console.log(isArray([])); // true
console.log(isArray([1,2,3])); // true
//判斷特殊情況,跨平臺框架
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
xArray = window.frames[window.frames.length-1].Array;
var arr = new xArray("1","2","3","4","5");
console.log(arr); // ["1","2","3","4","5"]
console.log(isArray(arr)); // true ~
這時候,可能又有人要說了,這種原型鏈的方法這么麻煩,有簡單一點的嗎,當然ECMA-262為我們引入了Array.isArray()方法,
四、Array.isArray()
isArray方法用來準確判斷一個值是否為陣列,對于IE9+、 Firefox 4+、Safari 5+、Opera 10.5+和Chrome都可以完美兼容,但是對于IE8之前的版本是不支持的,
但是個人感覺用法來說是最為簡便的:
Array.isArray([]) // true
總結
對于判斷一個物件是陣列的問題上,最好的方式如下:
var arr = [1,2,3];
var arr2 = [{ name : 'jack', age : 22 }];
function isArrayFn(value){
// 判斷Array.isArray的兼容性
if (typeof Array.isArray === "function") {
return Array.isArray(value);
}else{
return Object.prototype.toString.call(value) === "[object Array]";
// return obj.__proto__ === Array.prototype;
}
}
console.log(isArrayFn(arr)); // true
console.log(isArrayFn(arr2)); // true
補充:原生鏈的方法不僅看起來較為麻煩,而且執行效率也幾乎慢了Array.isArray()一倍,所以我們為了提高代碼的執行效率,所以我們可以最先判斷Array.isArray()的兼容性問題,之后再考慮選取原型鏈的方法,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/168279.html
標籤:其他
下一篇:單元測驗和Mock
