JavaScript 在類型判斷上確實是有比較多的坑,在不使用 ES5 的 Array.isArray() 的狀況下,如何判斷呢?javascript
javascript 弱類型的語言就是有比較多的坑,單純的typeof 是很無力的。因此用它來判斷數組確定是不行的。java
typeof 1 // number typeof undefined // undefined typeof null // object typeof [] // object typeof {} //object typeof function (){} // function
那麼言歸正傳正傳,該如何判斷。數組
Array 對象都是有length 屬性的,可不能夠判斷lengthapp
function isArray(array) { return (typeof array === 'object' && typeof array.length === 'number') }
與這個相似的是函數
function isArray(array) { return (typeof array === 'object' && !isNaN(array.length)) }
可是這個存在的問題是,對於有length屬性的對象,則會出現判斷失誤的問題
好比:.net
var fakeArray = { length: 10, value: 'Fake Array' }
var arr = [1, 2, 3] arr instanceof Array // constructor 指向了原型 arr.constructor === Array
但在多iframe的狀況下,因爲每一個iframe 是一個獨立的環境,它們之間不不共享原型鏈,則經過原型進行判斷會出現錯誤prototype
var iframe = document.createElement('iframe') document.body.appendChild(iframe) xArray = window.frames[window.frames.length-1].Array var arr = new xArray(1,2,3) // [1,2,3] // 正確的判斷 Array.isArray(arr) // true // 有問題的判斷 arr instanceof Array // false arr.constructor === Array // false
適用於全部環境,只支持原生的對象,Object的toString()方法不能檢測非原生構造函數的構造函數名。開發人員自定義的任何構造函數都將返回[object Object]。在任何值上直接調用Object的原生toString()方法,都會返回[object NativeConstrctorName]格式的字符串,每一個類內部都有一個class屬性,這個屬性中就指定了上述字符串中構造函數名。
code
Object.prototype.toString.call(array) === '[object Array]'
不過,上面的方案也存在必定問題,在ES6 中這樣的判斷能夠被欺騙htm
var obj = {}; // ES6 Symbol obj[Symbol.toStringTag] = 'Array'; // true console.log(isArray(obj));
在ES5 以後,就老老實實用Array.isArray 來判斷,ES5以前能夠使用上面pollyfill。對象
if (!Array.isArray) { return Object.prototype.toString.call(array) === '[object Array]'; }
以此延伸,那麼判斷其餘類型就能夠使用相似的方法
var is = function (obj,type) { return (type === "Null" && obj === null) || (type === "Undefined" && obj === void 0 ) || (type === "Number" && isFinite(obj)) || Object.prototype.toString.call(obj).slice(8,-1) === type; }
參考: