如何检测一个variables是否是一个数组
什么是最好的事实上的标准的跨浏览器方法来确定JavaScript中的variables是否是一个数组?
在网上search有一些不同的build议,一些很好,很多是无效的。
例如,以下是一个基本的方法:
function isArray(obj) { return (obj && obj.length); }
但是,请注意,如果数组为空,或者obj实际上不是数组,而是实现了长度属性等等会发生什么情况。
那么哪个实现在实际工作中是最好的,跨浏览器并且仍然有效地执行?
在JS中检查对象的types是通过instanceof
完成的
obj instanceof Array
如果对象跨越边框传递,每个框架都有自己的Array
对象,则这将不起作用。 你可以通过检查对象的内部[[Class]]属性来解决这个问题。 为了得到它,使用Object.prototype.toString()
(这是保证由ECMA-262工作):
Object.prototype.toString.call(obj) === '[object Array]'
这两种方法只适用于实际的数组,而不是类似于arguments
对象或节点列表的类似数组的对象。 由于所有类似数组的对象都必须有一个数字length
属性,所以我会检查它们是这样的:
typeof obj !== 'undefined' && obj !== null && typeof obj.length === 'number'
请注意,string将通过此检查,这可能会导致问题,因为IE不允许通过索引访问string的字符。 因此,您可能需要将typeof obj !== 'undefined'
更改为typeof obj === 'object'
以排除与'object'
不同的types的基元和宿主对象。 这仍然会让string对象通过,这将不得不手动排除。
在大多数情况下,你真正想知道的是你是否可以通过数字索引迭代对象。 因此,检查对象是否具有名为0
的属性可能是一个好主意,可以通过以下其中一种检查来完成:
typeof obj[0] !== 'undefined' // false negative for `obj[0] = undefined` obj.hasOwnProperty('0') // exclude array-likes with inherited entries '0' in Object(obj) // include array-likes with inherited entries
对象的强制转换对于类似数组的基元(即string)正确工作是必要的。
下面是对JS数组进行健壮检查的代码:
function isArray(obj) { return Object.prototype.toString.call(obj) === '[object Array]'; }
和可迭代的(即非空的)类似数组的对象:
function isNonEmptyArrayLike(obj) { try { // don't bother with `typeof` - just access `length` and `catch` return obj.length > 0 && '0' in Object(obj); } catch(e) { return false; } }
ECMAScript 5th Edition的到来为我们提供了一个最可靠的testing方法,如果一个variables是一个数组Array.isArray() :
Array.isArray([]); // true
虽然这里接受的答案将在大多数浏览器的跨框架和窗口上工作, 但它不适用于Internet Explorer 7及更低版本 ,因为从另一个窗口调用的数组的Object.prototype.toString
将返回[object Object]
,而不是[object Array]
。 IE 9似乎已经退化到这种行为(见下面更新的修复)。
如果你对这个博客文章感兴趣的话,我不会深入到这个解决scheme的所有细节部分。 但是,如果您想要一个适用于所有浏览器的解决scheme,则可以使用:
(function () { var toString = Object.prototype.toString, strArray = Array.toString(), jscript = /*@cc_on @_jscript_version @*/ +0; // jscript will be 0 for browsers other than IE if (!jscript) { Array.isArray = Array.isArray || function (obj) { return toString.call(obj) == "[object Array]"; } } else { Array.isArray = function (obj) { return "constructor" in obj && String(obj.constructor) == strArray; } } })();
这不是完全牢不可破的,但只有被试图打破它的人才会被打破。 它解决了IE7和IE9以下的问题。 该错误仍然存在于IE 10 PP2中 ,但在发布之前可能会被修复。
PS,如果你不确定解决scheme,那么我build议你testing一下你的内容和/或阅读博客文章。 如果使用条件编译不舒服,还有其他可能的解决scheme。
Crockford在“The Good Parts”的第106页有两个答案。 第一个检查构造函数,但会给不同的框架或窗口带来错误的否定。 这是第二个:
if (my_value && typeof my_value === 'object' && typeof my_value.length === 'number' && !(my_value.propertyIsEnumerable('length')) { // my_value is truly an array! }
克罗克福德指出,这个版本将识别arguments
数组作为数组,即使它没有任何数组方法。
他对这个问题的有趣讨论从第105页开始。
这里还有一个有趣的讨论(好的部分),包括这个build议:
var isArray = function (o) { return (o instanceof Array) || (Object.prototype.toString.apply(o) === '[object Array]'); };
所有的讨论使我从不想知道某物是否是一个数组。
jQuery实现了一个isArray函数,这表明最好的方法是
function isArray( obj ) { return toString.call(obj) === "[object Array]"; }
(取自jQuery v1.3.2的片段 – 稍微调整一下,使之脱离上下文)
从上师John Resig和jquery窃取:
function isArray(array) { if ( toString.call(array) === "[object Array]") { return true; } else if ( typeof array.length === "number" ) { return true; } return false; }
一旦你决定它是一个数组,你将如何处理这个值?
例如,如果打算枚举包含的值,如果它看起来像一个数组,或者如果它是一个对象被用作一个哈希表,然后下面的代码得到你想要的(当闭包函数返回其他东西而不是“undefined”。注意,它不会遍历COM容器或枚举;这只是读者的练习):
function iteratei( o, closure ) { if( o != null && o.hasOwnProperty ) { for( var ix in seq ) { var ret = closure.call( this, ix, o[ix] ); if( undefined !== ret ) return ret; } } return undefined; }
(注意:“o!= null”testingnull和undefined)
使用示例:
// Find first element who's value equals "what" in an array var b = iteratei( ["who", "what", "when" "where"], function( ix, v ) { return v == "what" ? true : undefined; }); // Iterate over only this objects' properties, not the prototypes' function iterateiOwnProperties( o, closure ) { return iteratei( o, function(ix,v) { if( o.hasOwnProperty(ix) ) { return closure.call( this, ix, o[ix] ); } }) }
如果你想跨浏览器,你想要jQuery.isArray 。
在w3school有一个例子,应该是相当标准的。
要检查一个variables是否是一个数组,他们使用类似的东西
function arrayCheck(obj) { return obj && (obj.constructor==Array); }
在Chrome,Firefox,Safari,ie7上进行testing
在PHPJS网站上可以find这个函数最好的研究和讨论版本之一。 你可以链接到包,或者你可以直接去函数 。 我强烈build议在JavaScript中使用构造良好的PHP函数的网站。
没有足够的引用等于构造函数。 有时他们有不同的构造函数的引用。 所以我使用它们的string表示。
function isArray(o) { return o.constructor.toString() === [].constructor.toString(); }
用obj.constructor==Array
replaceArray.isArray(obj)
样品:
Array('44','55').constructor==Array
返回true(IE8 / Chrome)
'55'.constructor==Array
返回false(IE8 / Chrome)