// assumes Array.isArray or a polyfill is available
function canAccessAsArray(item) {
if (Array.isArray(item)) {
return true;
}
// modern browser such as IE9 / firefox / chrome etc.
var result = Object.prototype.toString.call(item);
if (result === "[object HTMLCollection]" || result === "[object NodeList]") {
return true;
}
//ie 6/7/8
if (typeof item !== "object" || !item.hasOwnProperty("length") || item.length < 0) {
return false;
}
// a false positive on an empty pseudo-array is OK because there won't be anything
// to iterate so we allow anything with .length === 0 to pass the test
if (item.length === 0) {
return true;
} else if (item[0] && item[0].nodeType) {
return true;
}
return false;
}
for (var i=0, l=obj.length; i<l; ++i) {
var item = obj[i];
}
所以测试很简单:
function isArrayLike(obj) {
if (!obj) return false;
var l = obj.length;
if (typeof l != 'number' || l < 0) return false;
if (Math.floor(l) != l) return false;
// fast check
if (l>0 && !((l-1) in obj)) return false;
// more complete check (optional)
for (var i=0; i<l; ++i) {
if (!(i in obj)) return false;
}
return true;
}
function isArrayLike(o) {
var n;
return ({}).toString.call(o).split(' ')[1] in {"String]":1,"Array]":1} || o!=null
// Confirm that o.length is a non-negative integer
&& (n=o.length)===Math.abs(n|0)
// And when non-zero confirm that o.length-1 is a property in o
&& (!n || n-1 in o);
}
这个函数检查所有索引元素的存在性,这使得它的时间复杂度为O(n)。
function isArrayLikeStrict(o) {
var n = 0;
if (({}).toString.call(o).split(' ')[1] in {"String]":1,"Array]":1} || o!=null
// Confirm that o.length is a non-negative integer
&& (n=o.length)===Math.abs(n|0)
) {
// Confirm existence of all indexed elements
while (n--) if(!(n in o)) return false;
return true;
}
return false;
}
function isArrayLikeLessStrict(o) {
var n = 0;
if (({}).toString.call(o).split(' ')[1] in {"String]":1,"Array]":1} || o!=null
// Confirm that o.length is a non-negative integer
&& (n=o.length)===Math.abs(n|0)
) {
// Confirm existence of all indexed elements
while (n) {
console.log(n);
if(!(n-1 in o)) return false;
n = n/2|0;
}
return true;
}
return false;
}
8条答案
按热度按时间r7knjye21#
有一种方法可以检查一个对象是否类似于数组,即使其中没有元素,在这里使用这个函数:
这使用了我偶然发现的一个小技巧,它允许您确定对象是(1)数组、(2)类数组还是(3)类对象/类对象。
唯一的缺点是,对于添加了类似于对象的属性的类似数组的对象,如
arguments
,它不能正常工作hzbexzde2#
我认为没有什么比扩展本机对象更简单、更有表现力了:
这种方法可能会导致框架之间的冲突,但是,我建议您不要使用
isArrayLike
函数与其名称不符的框架。1zmg4dgp3#
正如我在这个主题的研究中发现的那样,你只有两个选择:
1.您可以只查看
.length
属性,并接受似乎具有适当.length
属性的任何对象,这些对象不是您知道应该消除的任何其他对象(如函数)。1.您可以检查特定的类似数组的对象(
HTMLCollection
、nodeList
)并偏向它们。下面是第一种方法的两个选项--一个不接受零长度,另一个接受零长度(这两个选项结合了gilly 3的建议以及我们在jQuery的类似函数中看到的内容):
当然,这将为带有
.length === 0
的项报告false
。如果您希望允许.length === 0
,则可以使逻辑也包括这种情况。一些测试用例:http://jsfiddle.net/jfriend00/3brjc/
2)在检查它不是一个实际的数组之后,可以编写代码来检查特定种类的类似数组的对象(例如
nodeList
、HTMLCollection
)。例如,当我想确保包含nodeList和HTMLDollection类数组对象时,我使用了以下方法:
sy5wg1nm4#
您可以检查对象是否为 iterable:
不过要小心,对于字符串***,**返回true。如果这是一个问题,请排除它们:
然后使用迭代器访问元素,或者如果您想使用常规的 array[0] 方式,只需添加一个长度检查属性。
完整的isArrayLike函数:
soat7uwm5#
好吧,这取决于你所说的类似于数组的东西,也许你可以用一个for循环来迭代它,就像这样:
所以测试很简单:
当然,这不会捕捉到稀疏填充的数组,但是话又说回来,它们真的被用作数组吗?NodeList和类似的东西不会被稀疏填充。
"尽情享受吧"
rxztt3cl6#
在JavaScript中,类似数组的对象是包含
length
属性的对象,该属性具有非负整数值。长度大于零的类似数组的对象还包含额外的n
属性,该属性从[0]开始,一直到[n-1],其中n =length
的值。在此定义下,字符串也类似数组,并在以下函数中返回true。最后我写了三个函数,因为不检查所有索引元素的存在可以保存时间,这些函数可以在旧的浏览器中工作。
这个函数只检查最后一个元素的存在,这使得它的时间复杂度为O(1)。
这个函数检查所有索引元素的存在性,这使得它的时间复杂度为O(n)。
这个函数检查log 2(n)+1个索引元素的存在性,这使得它的时间复杂度为O(log n),这可能是你最好的选择,它比第一个更严格,但避免了第二个的O(n)复杂度。
sigwle7e7#
从技术上讲,(几乎)根据标准(ECMAScript 2015语言规范§7.3.17,
CreateListFromArrayLike (obj [, elementTypes] )
),每个对象都是“类似数组的”(因为undefined
的类型强制):7.3.17从类数组创建列表(对象[,元素类型])
抽象操作CreateListFromArrayLike用于创建List值,其元素由类似数组的对象 obj 的索引属性提供。可选参数 elementTypes 是一个List,其中包含ECMAScript语言类型的名称,这些名称允许用于创建的List的元素值。此抽象操作执行以下步骤:
1.突然返回(* 对象 )。
1.如果未传递 elementTypes,则让 elementTypes 为(未定义、空、布尔、字符串、符号、数字、对象)。
1.如果类型(obj)不是Object,则引发TypeError异常。
1.设 len 为目标长度(Get(obj,
"length"
))。1.突然返回(len)。
1.令 list 为空List。
1.令 index 为0。
1.当 index〈len 时重复
1.令 * 索引名称 * 为目标字符串( 索引 )。
1.令 next 为Get( 对象 , 索引名称 )。
1.突然返回( 下一次 *)。
1.如果类型(next)不是 elementTypes 的元素,则引发TypeError异常。
1.追加 next 作为 list 的最后一个元素。
1.将 * 索引 * 设置为 * 索引 * + 1。
1.返回 * 列表 *。
通过https://www.browserling.com/tools/html-to-markdown生成
new9mtju8#
Array是具有以下属性的值:
1.其类型为object
1.它具有等于或大于0的 * length * 属性。
1.所有基于值的键都是数字,并且大于或等于0。