在Javascript中区分数组和"哈希"

Jam*_*ong 14 javascript

为了使我的一个函数的语法更好,我需要能够判断一个特定的参数是一个数组还是"哈希"(我知道它只是对象).

Typeof不起作用,因为它们都返回相同的东西

typeof {foo:"bar"} // Object

typeof ["foo","bar"] // Object

那么我如何区分这两者呢?

我知道这有效,但我希望有更好的方法

({foo:"bar"}).constructor // Object()

(["foo","bar"]).constructor // [ undefined ]

编辑 啊,似乎[firebug中的[undefined]与Array是一样的.有点奇怪.

gbl*_*zex 11

你可以像SLaks建议的那样检查长度属性,但是一旦你传递了一个函数对象,你就会感到惊讶,因为它实际上有一个length属性.此外,如果对象定义了一个length属性,你将再次得到错误的结果.

你最好的选择可能是:

function isArray(obj) {
    return Object.prototype.toString.call(obj) === "[object Array]";
}
Run Code Online (Sandbox Code Playgroud)

jQuery使用它,还有一对"其他人"...... :)

它比实例方式更失败.以下文章还建议了该方法:

'instanceof'被认为是有害的(或者如何编写一个强大的'isArray') (@ kagax)

另外要补充一点,这个功能几乎与Array.isArrayES 5规范中的功能相同:

15.4.3.2 Array.isArray(arg)

  1. 如果Type(arg)不是Object,则返回 false.
  2. 如果arg的[[Class]]内部属性的值是"Array",则返回true.
  3. 返回false.

  • 这个例子来自jQuery,它出于某种原因将`Object.prototype.toString`放在变量`toString`中.它不会按原样运作. (3认同)

bob*_*nce 7

something instanceof Array在单个文档中正常工作,但如果您开始在不同窗口之间传递数组,则会失败,因为Array一个窗口与另一个窗口是不同的对象Array.如果你不打算做跨窗口脚本(一般来说,值得避免),我建议坚持这一点.

如果您需要跨窗口支持,事情就会复杂一些.在未来,故事很简单,因为ECMAScript第五版定义了一个函数来完成这个:

Array.isArray([1]);   // -> true
Run Code Online (Sandbox Code Playgroud)

您应该使用此功能,因为它是唯一可靠且标准认可的方式.但是,今天的许多浏览器还不支持它.

如果它不可用,你必须依赖Object#toString序列化,这是丑陋和略有狡猾.虽然它通常可以与当今的浏览器一起可靠地工作,但是可以想象它可能不会(主要与宿主对象有关).

您可以将此回退方法放入Array不支持它的浏览器中,然后Array.isArray随时使用:

if (!('isArray' in Array)) {
    Array.isArray= function(o) {
        return Object.prototype.toString.call(o)==='[object Array]';
    };
}
Run Code Online (Sandbox Code Playgroud)

至于constructor,永远不要使用它.它并非在任何地方都可用,它没有按照您的想法行事.使用它几乎总是一个错误.

  • bobince:+1*谢谢*关于不使用`constructor`的注释.非常感激.我删除了我的答案. (3认同)