为了使我的一个函数的语法更好,我需要能够判断一个特定参数是一个数组还是“哈希”(我知道它只是对象)。
Typeof不起作用,因为它们都返回相同的东西
typeof {foo:"bar"} // Object
typeof ["foo","bar"] // Object
那么我如何区分这两者?
我知道有效,但我希望有一个更好的方式
({foo:"bar"}).constructor // Object()
(["foo","bar"]).constructor // [ undefined ]
修改 啊,在firebug中似乎[undefined]与Array相同。有点奇怪。
答案 0 :(得分:11)
你可以像SLaks建议的那样检查长度属性,但是一旦你传递了一个函数对象,你就会感到惊讶,因为它实际上有一个length属性。此外,如果对象定义了一个length属性,你将再次得到错误的结果。
你最好的选择可能是:
function isArray(obj) {
return Object.prototype.toString.call(obj) === "[object Array]";
}
jQuery使用它,以及一对“其他人......”)
它比实例方式更失败。该方法也由以下文章提出:
'instanceof' considered harmful (or how to write a robust 'isArray') (@ kagax)
另外要补充的是,此功能几乎与ES 5规范中的Array.isArray
功能相同:
15.4.3.2 Array.isArray(arg)
- 如果Type( arg )不是Object,则返回 的假即可。
- 如果[[Class]]的值 arg 的内部属性是“数组”, 然后返回 true 。
- 返回 false 。
醇>
答案 1 :(得分:7)
something instanceof Array
在单个文档中正常工作,但如果您开始在不同窗口之间传递数组,则会失败,因为一个窗口中的Array
与另一个窗口中的Array
不同。如果您无意进行跨窗口脚本编写(一般情况下,值得避免),我建议您坚持使用。
如果您需要跨窗口支持,事情会更复杂一些。在未来,故事很简单,因为ECMAScript第五版定义了一个功能来完成这个:
Array.isArray([1]); // -> true
您应该使用此功能,因为它是唯一可靠且标准认可的方式。但是,今天的许多浏览器还不支持它。
如果它不可用,你必须依赖Object#toString
序列化,这是丑陋的,有点狡猾。虽然它通常可以在今天的浏览器中可靠地工作,但是可以想象它可能没有(主要与宿主对象有关)。
您可以在不支持此浏览器的浏览器上将此回退方法修改为Array
,然后始终使用Array.isArray
:
if (!('isArray' in Array)) {
Array.isArray= function(o) {
return Object.prototype.toString.call(o)==='[object Array]';
};
}
对于constructor
,永远不要使用它。它并非在任何地方都可用,它没有按照您的想法行事。使用它几乎总是一个错误。
答案 2 :(得分:3)
我认为最优雅的方法是简单地使用instanceof
运算符:
if (myVar instanceof Array)
doSomething();
示例:
[] instanceof Array // true
{} instanceof Array // false
{length:100} instanceof Array // false
null instanceof Array // false
请注意,从另一个iFrame测试对象时会失败(请参阅@galambalazs和@bobince的答案)
答案 3 :(得分:1)
检查length
属性:
"length" in {foo:"bar"} //false
"length" in ["foo","bar"] //true
答案 4 :(得分:0)
此typeof函数用于纠正typeof运算符的数组/对象冲突,和 null / object碰撞。但是它不能跨框架或跨窗口工作。请参阅源代码以获取适用于这些版本的更高级版本。
function typeOf(value) {
var s = typeof value;
if (s === 'object') {
if (value) {
if (value instanceof Array) {
s = 'array';
}
} else {
s = 'null';
}
}
return s;
}