有没有办法检查某个对象是否类似于#34;就像这些类型的对象一样:
Array.isArray
时,这些将返回false 我想您可以检查是否存在.length
属性,但非类数组对象可以包含.length
属性。我猜这些共同的东西是数组访问器。
答案 0 :(得分:9)
我在这个主题的研究中发现,你只有几个选择:
您只能查看.length
属性,并接受任何似乎具有适当.length
属性的对象,这些属性不是您知道应该消除的任何其他内容(例如一个功能)。
您可以检查特定的类似数组的对象(HTMLCollection
,nodeList
)并偏向它们。
这是第一种方法的两个选项 - 一个不接受零长度的方法和一个方法(这些包含gilly3的建议以及我们在jQuery中看到的类似功能):
// see if it looks and smells like an iterable object, but don't accept length === 0
function isArrayLike(item) {
return (
Array.isArray(item) ||
(!!item &&
typeof item === "object" &&
item.hasOwnProperty("length") &&
typeof item.length === "number" &&
item.length > 0 &&
(item.length - 1) in item
)
);
}
当然,这会为false
的项目报告.length === 0
,如果您想允许.length === 0
,那么也可以使逻辑包含该情况。
// see if it looks and smells like an iterable object, and do accept length === 0
function isArrayLike(item) {
return (
Array.isArray(item) ||
(!!item &&
typeof item === "object" &&
typeof (item.length) === "number" &&
(item.length === 0 ||
(item.length > 0 &&
(item.length - 1) in item)
)
)
);
}
一些测试用例:http://jsfiddle.net/jfriend00/3brjc/
2)在检查它是否不是实际数组之后,您可以编码以检查特定类型的类似数组的对象(例如nodeList
,HTMLCollection
)。
例如,这是我想要确保包含nodeList和HTMLCollection类似数组的对象时使用的方法:
// 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;
}
答案 1 :(得分:0)
嗯,这取决于你的意思是数组式的。可能你可以用这样的for循环迭代:
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;
}
当然,这不会捕获人口稀少的数组,但话说再次,他们真的被用作数组吗?节点列表等不会被稀疏地填充。
享受!
答案 2 :(得分:0)
有一种方法可以检查对象是否类似于数组,即使其中没有元素,也可以使用此函数:
isArrayLike = function (_) {
_[0] = 0; return [].slice.call(_).length >= Object.values(_).length;
}
这使用了一个我意外发现的小黑客,它允许你确定一个对象是(1)一个数组,(2)数组,还是(3)对象/对象。
唯一的缺点是,对于添加了类似对象属性的数组,它无法正常工作,例如arguments
答案 3 :(得分:0)
您可以检查对象是否为可迭代:
function isIterable(o){
return (o!=null && typeof(o[Symbol.iterator])==='function');
}
请注意, 为字符串返回true 。如果有问题,请排除它们:
function isIterable(o){
return (o!=null && typeof(o[Symbol.iterator])==='function' && typeof(o)!=='string');
}
然后要么使用迭代器访问元素,要么如果要使用常规的 array [0] 方法,只需添加一个length属性检查。
完整的isArrayLike函数:
function isArrayLike(a){
return (
a!=null &&
typeof(a[Symbol.iterator])==='function' &&
typeof(a.length)==='number' &&
typeof(a)!=='string'
);
}
答案 4 :(得分:0)
从技术上来说 ,(几乎)每个对象都是根据标准({{的类型为undefined
的类型,因为类型为"length"
3}}):
7.3.17 CreateListFromArrayLike(obj [,elementTypes])
抽象操作CreateListFromArrayLike用于创建一个List值,其值由类似数组的对象 obj 的索引属性提供。可选参数 elementTypes 是一个ECMAScript 2015 Language Specification §7.3.17,
CreateListFromArrayLike (obj [, elementTypes] )
,包含创建的List元素值所允许的ECMAScript语言类型的名称。此抽象操作执行以下步骤:
- List( obj )。
- 如果未传递 elementTypes ,则使 elementTypes 为(未定义,空,布尔,字符串,符号,数字,对象)。
- 如果ReturnIfAbrupt( obj ) 不是对象,则引发 TypeError 异常。
- 让 len 是Type(ToLength( obj ,{{1}}))。
- Get( len )。
- 让列表为空ReturnIfAbrupt。
- 让 index 为0。
- 在索引 <<< em> len 时重复
- 让 indexName 为List( index )。
- 让 next 成为ToString( obj , indexName )。
- Get(下一个)。
- 如果ReturnIfAbrupt(下一个) 不是 elementTypes 的元素,则引发 TypeError 异常。
- 将 next 添加为 list 的最后一个元素。
- 将 index 设置为 index +1。
- 返回列表。
通过Type
生成答案 5 :(得分:0)
我之所以编写此函数,是因为我需要可以在旧浏览器中正常工作的东西。
prepareStatement