JavaScript 在範例推斷上確實是有比較多的坑,在不運用 ES5 的 Array.isArray() 的情況下,怎樣推斷呢?
起首摒棄typeof
javascript 弱範例的言語就是有比較多的坑,純真的typeof 是很無力的。所以用它來推斷數組肯定是不可的。
typeof 1 // number
typeof undefined // undefined
typeof null // object
typeof [] // object
typeof {} //object
typeof function (){} // function
那末言歸正傳正傳,該怎樣推斷。
思緒一:length 屬性推斷
Array 對象都是有length 屬性的,可不能夠推斷length
function isArray(array) {
return (typeof array === 'object' && typeof array.length === 'number')
}
與這個相似的是
function isArray(array) {
return (typeof array === 'object' && !isNaN(array.length))
}
然則這個存在的題目是,關於有length屬性的對象,則會湧現推斷失誤的題目
比方:
var fakeArray = {
length: 10,
value: 'Fake Array'
}
思緒二:對Array實例對象的原型舉行推斷。
var arr = [1, 2, 3]
arr instanceof Array
// constructor 指向了原型
arr.constructor === Array
但在多iframe的情況下,因為每一個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) // [1,2,3]
// 準確的推斷
Array.isArray(arr) // true
// 有題目的推斷
arr instanceof Array // false
arr.constructor === Array // false
思緒三: Object.prototype.toString.call() 要領
適用於一切環境,只支撐原生的對象,Object的toString()要領不能檢測非原生組織函數的組織函數名。開發人員自定義的任何組織函數都將返回[object Object]。在任何值上直接挪用Object的原生toString()要領,都邑返回[object NativeConstrctorName]花樣的字符串,每一個類內部都有一個class屬性,這個屬性中就指定了上述字符串中組織函數名。
Object.prototype.toString.call(array) === '[object Array]'
不過,上面的計劃也存在肯定題目,在ES6 中如許的推斷能夠被誑騙
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;
}
參考: