Javascript 检查对象是否与数组相似
是否有方法检查对象是否为“类似数组”的对象,如以下类型的对象:Javascript 检查对象是否与数组相似,javascript,arrays,Javascript,Arrays,是否有方法检查对象是否为“类似数组”的对象,如以下类型的对象: 阵列(duh) 类型化数组(Uint8Array等),当使用Array.isArray时,这些数组将返回false 参数对象 节点主义者* 还有一些我不能马上想到的 我想您可以检查是否存在.length属性,但非数组类对象可以包含.length属性。我想这些都有一个共同点,那就是数组存取器。我在这方面的研究中发现,您只有两个选择: 您只能查看.length属性,并接受任何似乎具有适当.length属性的对象,该属性不是您知道应该
- 阵列(duh)
- 类型化数组(Uint8Array等),当使用
时,这些数组将返回falseArray.isArray
- 参数对象
- 节点主义者*
- 还有一些我不能马上想到的
我想您可以检查是否存在
.length
属性,但非数组类对象可以包含.length
属性。我想这些都有一个共同点,那就是数组存取器。我在这方面的研究中发现,您只有两个选择:
.length
属性,并接受任何似乎具有适当.length
属性的对象,该属性不是您知道应该消除的任何其他东西(如函数)HTMLCollection
,nodeList
),并偏向它们.length==0
的项目,这会报告false
,如果您希望允许.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)
)
)
);
}
一些测试用例:
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;
}
Object.prototype.isArrayLike = function(){ return false; };
Array.prototype.isArrayLike = function(){ return true; };
NodeList.prototype.isArrayLike = function(){ return true; };
HTMLCollection.prototype.isArrayLike = function(){ return true; };
//假设Array.isArray或polyfill可用
功能CAnacessasarray(项目){
if(阵列isArray(项目)){
返回true;
}
//现代浏览器,如IE9/firefox/chrome等。
var result=Object.prototype.toString.call(项目);
如果(结果==“[object HTMLCollection]”| |结果==“[object NodeList]”){
返回true;
}
//ie 6/7/8
if(typeof item!=“object”| |!item.hasOwnProperty(“length”)| | item.length<0){
返回false;
}
//空伪数组上的假阳性是可以的,因为不会有任何错误
//进行迭代,以便允许.length==0的任何内容通过测试
如果(item.length==0){
返回true;
}else if(项[0]&项[0]。节点类型){
返回true;
}
返回false;
}
好吧,这取决于你所说的“类数组”是什么意思。可能您可以使用for循环进行如下迭代:
for (var i=0, l=obj.length; i<l; ++i) {
var item = obj[i];
}
for(var i=0,l=obj.length;i0&&!(obj中的(l-1))返回false;
//更完整的检查(可选)
对于(var i=0;i我说没有什么比扩展本机对象的简单性和表达性更好的了:
// 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;
}
Object.prototype.isArrayLike = function(){ return false; };
Array.prototype.isArrayLike = function(){ return true; };
NodeList.prototype.isArrayLike = function(){ return true; };
HTMLCollection.prototype.isArrayLike = function(){ return true; };
这种方法可能会导致框架之间发生冲突,但是,我建议您与isArrayLike
函数与名称不符的框架保持距离。可以在此处使用此函数检查对象是否与数组相似,即使其中没有元素:
isArrayLike = function (_) {
_[0] = 0; return [].slice.call(_).length >= Object.values(_).length;
}
这使用了我意外发现的一个小技巧,可以让你确定一个对象是(1)数组,(2)类似数组,还是(3)类似对象/对象
唯一的缺点是,对于添加了类似对象属性的数组类,例如参数您可以检查对象是否可编辑:
但是要小心,为字符串返回true。如果这是一个问题,请排除它们:
function isIterable(o){
return (o!=null && typeof(o[Symbol.iterator])==='function' && typeof(o)!=='string');
}
然后,使用迭代器访问元素,或者如果要使用常规数组[0]方式,只需添加一个长度检查属性即可
完成类似isArrayLike的函数:
function isArrayLike(a){
return (
a!=null &&
typeof(a[Symbol.iterator])==='function' &&
typeof(a.length)==='number' &&
typeof(a)!=='string'
);
}
从技术上讲,(几乎)根据标准(),每个对象都是“类似数组的”(因为未定义的
的类型强制):
7.3.17 CreateListFromArrayLike(obj[,elementTypes])
抽象操作CreateListFromArrayLike用于创建一个列表值,该列表值的元素由类似数组的对象obj的索引属性提供。可选参数elementTypes是一个包含ECMAScript语言类型名称的参数,该语言类型允许创建的元素值。此抽象操作执行以下步骤:
(obj)
如果未传递elementTypes,则让elementTypes为(未定义、Null、布尔、字符串、符号、数字、对象)
如果(obj)
不是对象,抛出类型错误
设len为((obj,“length”
))
(len)
让列表为空
设索引为0
在index时重复,我编写了这个函数,因为我需要在旧浏览器中工作的东西
function isArrayLike(object) {
var length
if (object==null) {// same as object==undefined
return false
}
try {// This throws an error in old browsers
return typeof object[Symbol.iterator]=="function"
}
catch (e) {
// Check that object.length is a non-negative integer
return (length=object.length)===Math.abs(length|0)
// And when non-zero check that length-1 is in object
&& (typeof object=="string" || !length || length-1 in object)
}
}
检查是否存在<代码>(0)< /代码>?但是空数组可能失败。考虑到,但是我的函数可以通过一个空数组。字符串也可以使用方括号,你只指字符串中的一个字符。不确定是否考虑字符串是数组(不)。DOM元素与数组不同,但节点列表与数组不同。也许你可以坚持你的函数总是像数组一样传递,希望是最好的:)我将带有整数id的对象存储在数组中,id作为数组索引。由于这些数据来自于从1开始对记录进行编号的数据库,因此索引0处没有元素,即使长度大于0。我使用数组而不是对象,因为有时我喜欢使用数组方法,如.filter()
。我的阵列将无法通过你的检查。似乎函数的第一行应该包含对数组的项实例的检查
function isArrayLike(object) {
var length
if (object==null) {// same as object==undefined
return false
}
try {// This throws an error in old browsers
return typeof object[Symbol.iterator]=="function"
}
catch (e) {
// Check that object.length is a non-negative integer
return (length=object.length)===Math.abs(length|0)
// And when non-zero check that length-1 is in object
&& (typeof object=="string" || !length || length-1 in object)
}
}