【问题标题】:NodeList object in javascriptjavascript中的NodeList对象
【发布时间】:2011-03-31 14:27:09
【问题描述】:

谁能告诉我 NodeList 是什么类型的对象。我读到它是一个类似数组的对象,可以通过括号表示法访问它,例如var a = someNode.childNode[0];。这怎么可能,因为通过括号符号我们只能访问对象的属性,而且我知道我们不能拥有

【问题讨论】:

    标签: javascript nodelist


    【解决方案1】:

    NodeListDOM elements 的集合。它就像一个数组(但它不是)。要使用它,您必须将其转换为常规 JavaScript 数组。下面的 sn-p 可以为你完成工作。

    const nodeList = document.getElementsByClassName('.yourClass'),
          nodeArray = [].slice.call(nodeList);
    

    更新:

    // newer syntax
    const nodeList = Array.from(document.querySelectorAll('[selector]'))
    
    // or
    const nodeList = [...document.querySelectorAll('[selector]')]
    

    【讨论】:

    • [].slice.call(nodeList) 对我来说就像一个魅力。我很想知道它为什么/如何工作。
    • 基本上javascript将节点列表视为一个数组,因为您正在使用调用方法将空数组的内容设置为节点列表。然后,只需 slice 方法返回其自身的精确副本(当不带参数使用时)。我希望这回答了你的问题(:
    • 比 for 循环优雅得多。也适用于 Array.prototype.forEach
    • @brielov 这并不完全正确,这里类似的[].forEach.call 范式批评 - toddmotto.com/ditch-the-array-foreach-call-nodelist-hack - 提供了更好的上下文。为了说明它与解释的不完全一样,尝试运行[1, 2, 3].slice.call(nodeList) 并注意你得到了相同的结果。尝试使用原始数组中的条目数,仍然得到相同的结果。
    • getElementsByClassName 返回一个 HTMLCollection,而不是 NodeList。这种差异很重要。 stackoverflow.com/q/15763358
    【解决方案2】:

    NodeList 是一个宿主对象,不受适用于原生 JavaScript 对象的常规规则的约束。因此,您应该坚持使用它的文档化 API,它由 length 属性和通过方括号属性访问语法访问其成员组成。您可以使用此 API 创建一个包含 NodeList 成员快照的 Array

    var nodeList = document.getElementsByTagName("div");
    var nodeArray = [];
    for (var i = 0; i < nodeList.length; ++i) {
        nodeArray[i] = nodeList[i];
    }
    

    【讨论】:

    • 那么这是否意味着一个nodeList不能被forin循环遍历呢?
    • @Triztian:确实如此。至少,不能保证它会起作用,而且我认为它在 IE 中不起作用。
    • 它在谷歌浏览器中也不起作用,您必须使用长度属性并像访问数组一样访问元素。
    • 啊哈,这解释了为什么 forEach 可以在 Array 类型上工作,但 不能bilbo.getElementsByTagName("taggins") 一起工作。
    【解决方案3】:

    NodeList 不是核心 Javascript 对象,它是由浏览器和 DOM 提供的。考虑一个返回动态或活动对象接口的函数,因此 forEach() 不可用,但您可以将其转换为真实数组以获取快照,例如

    // turns nodelist into an array to enable forEach
    function toArray(list) {
      var i, array = [];
      for  (i=0; i<list.length;i++) {array[i] = list[i];}
      return array;
    }
    

    详情:http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-536297177

    【讨论】:

    • 好吧,我想它是用 C++ 等语言实现的。即便如此,它们如何与 JavaScript 代码通信?
    • @user512783:这取决于浏览器和 javascript 引擎。你为什么想知道这个?
    • 我想弄清楚 DOM API 是否是用 EcmaScript 编写的,但据我所知,它不是。
    • 那么,您的问题是关于实施者的来源?火狐到这里:mxr.mozilla.org/mozilla-central/ident?i=nsIDOMNodeList
    【解决方案4】:

    JavaScript 就像酒精,它可以强制:

    var links = document.getElementsByTagName('a');
    Array.prototype.slice.call(links).forEach(function(anchor, index, arr) {
      anchor.addEventListener('click', onClickFN, false);
    });
    

    【讨论】:

    • ...或者只是Array.prototype.forEach.call(links, function() {}) ;)
    • 或者只是[].slice.call
    【解决方案5】:

    NodeLists “实时”,也就是说,当文档结构发生变化时它们会更新,以便它们始终具有最准确的信息。实际上,所有 NodeList 对象都是在访问时针对 DOM 运行的查询。

    任何时候你想迭代一个NodeList,最好用长度初始化第二个变量,然后将迭代器与那个变量进行比较:

    var divs = document.getElementsByTagName("div");
    
    for (var i=0, lens=divs.length; i  <  len; i++){
        var div = document.createElement("div");
        document.body.appendChild(div);
    } 
    

    NodeList 是一个类似数组的结构,但它实际上不是一个数组。您可以通过括号表示法访问数组值。

    【讨论】:

    • 你刚才的回答写在我正在看的书中。我不知道类似数组是什么意思。 EcmaScript 没有指定类似的内容。我猜这是一种实现技术。
    • 它不在 ECMA 的 DOM 规范中。你可以像数组一样迭代它(括号表示法),但你不能使用像 push()、splice() 或 reverse() 这样的数组方法来操作它。
    • 也就是说,它运行在浏览器级别的代码中(例如C++)?
    • 浏览器实现了它,所以可能是的。
    【解决方案6】:

    节点列表通常被实现为带有过滤器的节点迭代器。这意味着获取类似长度的属性是O(n),通过重新检查长度来迭代列表将是O(n^2)。

    var paragraphs = document.getElementsByTagName('p');
    for (var i = 0; i < paragraphs.length; i++) {
      doSomething(paragraphs[i]);
    }
    

    最好这样做:

    var paragraphs = document.getElementsByTagName('p');
    for (var i = 0, paragraph; paragraph = paragraphs[i]; i++) {
       doSomething(paragraph);
    } 
    

    这适用于所有集合和数组,只要数组不包含被视为布尔值 false 的内容。

    在您迭代 childNode 的情况下,您还可以使用 firstChild 和 nextSibling 属性。

    var parentNode = document.getElementById('foo');
    for (var child = parentNode.firstChild; child; child = child.nextSibling) {
      doSomething(child);
    }
    

    【讨论】:

    • 嗯,不只是 boolean false 值会打破循环,所有 falseyundefinednull0 等。 ) 值会...
    【解决方案7】:

    现在在 ES2015 中,您可以使用 Array.from 方法从任何类似数组的对象创建一个 Array 实例,所以这应该可以工作:

    const divList = Array.from( document.getElementsByTagName("div") );
    

    欲了解更多信息:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/from

    【讨论】:

    • 对我来说效果很好。 Chrome,2016 年 10 月。
    【解决方案8】:

    总结:

    NodeList 对象是表示节点集合的数据结构。 DOM 上下文中的节点可以是以下事物:

    1. 文档本身
    2. DOM 元素(即 HTML/SVG 元素)
    3. 文字
    4. cmets

    NodeList 不是数组,但是NodeList可迭代数据结构,这意味着我们可以遍历值(即节点项)使用for..of 循环。此外,它们在NodeList 的原型上还有一些不错的实用功能,这使得使用它们更加方便。

    示例:

    const parent = document.querySelector('.parent');
    const myNodeList1 = parent.childNodes; // this property is a Nodelist
    console.log(myNodeList1 instanceof NodeList);
    
    const myNodeList2 = document.querySelectorAll('.foo'); // this method returns a Nodelist
    console.log(myNodeList2 instanceof NodeList);
    
    // looping over the items of a nodelist
    for (let el of myNodeList2) {
      el.innerHTML = 'hi';
    }
    
    // getting the length of a nodeList 
    console.log(myNodeList2.length);
    <div class="parent">
      <div class="foo"></div>
      <div class="foo"></div>
    </div>

    这是 Nodelist 在浏览器 (chrome) 开发工具中的样子:


    您可以使用以下符号访问NodeList 的元素:

     myNodelist[0]; // grabs the first item of the NodeList
    

    因为你只是一个属性值对象使用一个键。在这个例子中,属性的键是数字零,值是 DOM 元素。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-01-17
      • 2021-02-07
      • 2013-01-07
      • 1970-01-01
      • 2019-03-25
      • 2016-06-30
      • 2019-11-21
      • 1970-01-01
      相关资源
      最近更新 更多