stp*_*tpe 100 javascript arrays
什么是确定JavaScript中的变量是否为数组的最佳事实标准跨浏览器方法?
在网上搜索有很多不同的建议,有些是好的,有些是无效的.
例如,以下是一种基本方法:
function isArray(obj) {
return (obj && obj.length);
}
Run Code Online (Sandbox Code Playgroud)
但是,请注意如果数组为空,或者obj实际上不是数组但实现了长度属性等会发生什么.
那么哪种实现在实际工作方面是最好的,跨浏览器并且仍然有效地执行?
Chr*_*oph 159
JS中对象的类型检查是通过instanceof
,即
obj instanceof Array
Run Code Online (Sandbox Code Playgroud)
如果对象通过帧边界传递,则这将不起作用,因为每个帧都有自己的Array
对象.您可以通过检查对象的内部[[Class]]属性来解决此问题.为了得到它,使用Object.prototype.toString()
(这保证由ECMA-262工作):
Object.prototype.toString.call(obj) === '[object Array]'
Run Code Online (Sandbox Code Playgroud)
这两种方法仅适用于实际数组,而不适用于arguments
对象或节点列表等类似数组的对象.由于所有类似数组的对象都必须具有数字length
属性,因此我会检查这些:
typeof obj !== 'undefined' && obj !== null && typeof obj.length === 'number'
Run Code Online (Sandbox Code Playgroud)
请注意,字符串将通过此检查,这可能会导致问题,因为IE不允许通过索引访问字符串的字符.因此,您可能希望更改typeof obj !== 'undefined'
为typeof obj === 'object'
排除具有与'object'
alltogether 类型不同的类型的基元和主机对象.这仍然会让字符串对象通过,这必须手动排除.
在大多数情况下,您实际想知道的是您是否可以通过数字索引迭代对象.因此,检查对象是否具有名为的属性可能是个好主意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
Run Code Online (Sandbox Code Playgroud)
强制转换为对象对于类似数组的基元(即字符串)是必要的.
这是JS数组的健壮检查代码:
function isArray(obj) {
return Object.prototype.toString.call(obj) === '[object Array]';
}
Run Code Online (Sandbox Code Playgroud)
和可迭代(即非空)数组类对象:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
And*_*y E 40
ECMAScript第5版的到来为我们提供了最可靠的测试方法,如果变量是一个数组,Array.isArray():
Array.isArray([]); // true
Run Code Online (Sandbox Code Playgroud)
虽然这里接受的答案适用于大多数浏览器的框架和窗口,但它不适用于Internet Explorer 7及更低版本,因为Object.prototype.toString
来自不同窗口的数组调用将返回[object Object]
,而不是[object Array]
.IE 9似乎也对这种行为感到退步(参见下面的更新修复).
如果您想要一个适用于所有浏览器的解决方案,您可以使用:
(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;
}
}
})();
Run Code Online (Sandbox Code Playgroud)
它并非完全牢不可破,但它只会被一个努力打破它的人打破.它适用于IE7及更低版本和IE9中的问题. 该错误仍然存在于IE 10 PP2中,但可能会在发布之前修复.
PS,如果你不确定解决方案,那么我建议你测试它的内容和/或阅读博客文章.如果您使用条件编译感到不舒服,还有其他可能的解决方案.
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!
}
Run Code Online (Sandbox Code Playgroud)
Crockford指出,该版本将arguments
数组标识为数组,即使它没有任何数组方法.
他对这个问题的有趣讨论从第105页开始.
这里还有一个有趣的讨论(后好部分),其中包括这个提议:
var isArray = function (o) {
return (o instanceof Array) ||
(Object.prototype.toString.apply(o) === '[object Array]');
};
Run Code Online (Sandbox Code Playgroud)
所有讨论都让我永远不想知道某些东西是否是一个数组.
归档时间: |
|
查看次数: |
53256 次 |
最近记录: |