我正在寻找一种有效的方法来测试 JavaScript 对象是否是某种有序对象。希望有人知道一个不涉及编写一些巨大的类型评估器函数的技巧。幸运的是,我不必处理 IE < 9,因此大多数较新的方法都可以。
根本问题是这样的:我需要弄清楚是否在对象上运行 for 循环或 for...in 循环。但是,我并不总是知道该对象是否是对象文字、数组、jQuery 对象等。
以下是我遇到的一些障碍:
我显然不能只使用 typeof
,因为数组和对象都会返回 object
。
我显然不能只使用Object.prototype.toString.call(collection)
,因为虽然数组确实返回[object Array]
,但自定义有序集合例如jQuery 对象仍然返回 [object Object]
并且我想要这个测试的全部原因是确定我是否需要 for 循环或 for...in 循环。在 jQuery 对象上使用 for...in 循环会包含实际上不属于集合的属性,从而使事情变得困惑。
我确实想出了一个如下所示的想法:
function isOrdered(item) {
// Begin by storing a possible length property
// and defaulting to false for whether the item
// is ordered.
var len = item.length, isOrdered = false;
// Functions are an easy test.
if (typeof item === 'function') {
return false;
}
// The Arguments object is the only object I know of
// with a native length property that can be deleted
// so we account for that specifically too.
if (Object.prototype.toString.call(item) === '[object Arguments]') {
return true;
}
// Attempt to delete the item's length property.
// If the item is ordered by nature, we won't get
// an error but we also won't be able to delete
// this property.
delete item.length;
// So if the length property still exists as a
// number, the item must be an ordered collection.
if (typeof item.length === 'number') {
isOrdered = true;
}
// If we originally stored a custom length property,
// put it back.
if (len !== undefined) {
item.length = len;
}
// Return the result.
return isOrdered;
}
到目前为止,这项技术已经通过了我的所有测试,但我担心删除自定义对象上的属性可能会导致性能下降,而且我不能 100% 确信我没有遗漏某些内容。大家有更好的想法吗?
最佳答案
你可以这样做:
function isOrdered(item) {
var len = item.constructor.prototype.length;
return len === +len;
}
如果“item”是一个 js 对象,则计算结果为 false,但如果它是数组或 jQuery 集合,则返回 true。
请注意,数组以外的事物可以具有数字长度属性(尝试检查函数的长度)。如果您可能传递整数或函数之类的东西,您将需要做一些更复杂的事情,但这应该捕获您在发布的代码中捕获的所有情况。另外,我认为删除 length 属性可能会产生不可预测的结果,因此我会避免这种方法,而选择不会改变您正在测试的对象的方法。
关于javascript - 如何测试 JavaScript 对象是否是有序类型的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20896296/