Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 迭代节点列表并移动其元素而不转换为数组的惯用方法是什么?_Javascript_Html_Arrays_Dom_Idioms - Fatal编程技术网

Javascript 迭代节点列表并移动其元素而不转换为数组的惯用方法是什么?

Javascript 迭代节点列表并移动其元素而不转换为数组的惯用方法是什么?,javascript,html,arrays,dom,idioms,Javascript,Html,Arrays,Dom,Idioms,这说明了问题所在。如果我正确理解了正在发生的事情,当我迭代并修改NodeList时,计数器变量I会错过其他节点 在那把小提琴里,我有两个列表,#一个和#二个,我想把#一个的所有子项移到#二个-- 一个 两个 三个 四个 四个 使用一些最小的JavaScript var lisToMove=document.getElementsByClassName('move'); var destination=document.getElementById('two'); 对于(var i=0;i

这说明了问题所在。如果我正确理解了正在发生的事情,当我迭代并修改
NodeList
时,计数器变量
I
会错过其他节点

在那把小提琴里,我有两个列表,
#一个
#二个
,我想把
#一个
的所有子项移到
#二个
--


  • 一个
  • 两个
  • 三个
  • 四个
  • 四个
  • 使用一些最小的JavaScript

    var lisToMove=document.getElementsByClassName('move');
    var destination=document.getElementById('two');
    对于(var i=0;i
    我知道我可以通过简单地将
    NodeList
    转换为
    Array
    并迭代
    Array
    来解决这个问题,但是我想知道,如果修改NodeList本身(而不仅仅是节点),迭代
    NodeList
    的正确方法是什么是吗?

    使用数组是这样做的正确方法。就像在循环数组时必须修改数组一样,您可能希望将修改部分和循环部分分开,这样一个部分就不会影响另一个

    在本例中,这是通过将节点列表转换为数组来完成的

    正如所建议的,您还可以使用
    querySelectorAll
    ,它返回一个冻结的节点列表

    我不确定有没有“正确”的方法。任何对您来说最容易实现、易于理解且有效的东西都应该是您所使用的。
    NodeList
    的一个简单的
    切片
    不应该是问题,即使仅仅创建一个新数组并复制对其内容的引用对性能的影响最小

    如果确实不想复制数组,可以向后循环
    节点列表
    ,确保对列表中该节点所做的任何更改实际上不会影响列表

    这里有一个例子来说明我的意思:

    var lisToMove = document.getElementsByClassName('move');
    var destination = document.getElementById('two');
    var i = lisToMove.length;
    while (i--) {
        destination.insertBefore(lisToMove[i], destination.firstChild);
    }
    
    演示:

    正如您所看到的,这并不是循环中一个简单的改变——插入节点的位置/方式的逻辑也必须改变,因为一切都是向后的。这就是为什么我将第二个参数改为
    insertBefore
    destination.firstChild
    。我相信还有其他方法来处理逻辑,但原则是一样的


    参考文献:

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

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

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

    在迭代子节点的情况下,还可以使用firstChild和nextSibling属性

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