Array.isArray()不适用于NodeList。还有其他选择吗?

时间:2014-02-11 22:48:27

标签: javascript arrays dom

我想确定变量是否是 DOM元素数组 NodeList或单个DOM元素。我尝试了Array.isArray(x),但在x = document.getElementsByClassName("test")时它返回false,因为它是NodeList而不是数组。

是否有替代方法来执行此操作?

我想出的解决方案是测试是否typeof x.attributes == "undefined",假设所有DOM元素都具有attributes属性。这有什么不对吗?

样品:

var x = document.getElementsByClassName("test");
var y = x[0];

console.log(Array.isArray(x));                   // returns false
console.log(typeof x.attributes == "undefined"); // returns true

console.log(Array.isArray(y));                   // returns false
console.log(typeof y.attributes == "undefined"); // returns false

示例html:

<div class="test"></div>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>

3 个答案:

答案 0 :(得分:2)

document.getElementsByClassName()会返回一个NodeList而不是一个数组,这就是你得失的原因。

在浏览器控制台中尝试此操作:

var x = document.getElementsByClassName("header")
x.isArray() // TypeError: Object #<NodeList> has no method 'isArray'

答案 1 :(得分:2)

你已经有两个答案解释,为什么它失败了。为了使它按照你期望的方式工作,你可以测试“类似数组”的对象:

来源: https://www.inkling.com/read/javascript-definitive-guide-david-flanagan-6th/chapter-7/array-like-objects

// Determine if o is an array-like object.
// Strings and functions have numeric length properties, but are 
// excluded by the typeof test. In client-side JavaScript, DOM text
// nodes have a numeric length property, and may need to be excluded 
// with an additional o.nodeType != 3 test.
function isArrayLike(o) {
    if (o &&                                // o is not null, undefined, etc.
        typeof o === "object" &&            // o is an object
        isFinite(o.length) &&               // o.length is a finite number
        o.length >= 0 &&                    // o.length is non-negative
        o.length===Math.floor(o.length) &&  // o.length is an integer
        o.length < 4294967296)              // o.length < 2^32
        return true;                        // Then o is array-like
    else
        return false;                       // Otherwise it is not
}

这基本上只测试对象是否具有一个正整数的长度属性。

在这里你可以看到它的实际效果: fiddle

如果对象是NodeList的实例,那么另一个更具体针对您的问题的解决方案就是测试:

console.log(x instanceof NodeList); // returns true
console.log(y instanceof NodeList); // returns false

答案 2 :(得分:1)

document.getElementsByClassName() returns an HTMLCollection, not an array:

elements = document.getElementsByClassName(names); // or:
elements = rootElement.getElementsByClassName(names);
  

元素是找到的元素的HTMLCollection。 names是一个字符串   表示要匹配的类名列表;类名是   由空格分隔的getElementsByClassName可以在任何地方调用   元素,不仅仅在文档上。调用它的元素   将被用作搜索的根源。

您需要先将该HTMLCollection转换为数组。

W3C spec还详细说明了这一点:

  

getElementsByClassName(classNames)方法必须返回列表   具有类名的元素classNames用于上下文对象。

     

给出以下XHTML片段:

<div id="example">
    <p id="p1" class="aaa bbb"/>
    <p id="p2" class="aaa ccc"/>
    <p id="p3" class="bbb ccc"/>
</div>
  

致电   document.getElementById('example')。getElementsByClassName('aaa')will   返回一个HTMLCollection,其中包含两个段落p1和p2。

     

对getElementsByClassName('ccc bbb')的调用只返回一个   然而,节点,即p3。打电话给   document.getElementById('example')。getElementsByClassName('bbb ccc')   会回归同样的事情。

     

对getElementsByClassName('aaa,bbb')的调用将不返回任何节点;   上面没有任何元素属于aaa,bbb类。

     

getElementById(elementId)方法必须返回第一个元素in   树顺序,在上下文对象的树中,其ID为elementId,   如果没有,则返回null。