Javascript 如何正确迭代getElementsByClassName

Javascript 如何正确迭代getElementsByClassName,javascript,html,dom,Javascript,Html,Dom,我是Javascript初学者 我通过窗口初始化网页。onload,我必须按类名(幻灯片)找到一堆元素,并根据一些逻辑将它们重新分配到不同的节点。我有一个函数Distribute(element),它接受一个元素作为输入并进行分发。我想做类似的事情(例如,如所述或所述): var slides=getElementsByClassName(“幻灯片”); 对于(变量i=0;i

我是Javascript初学者

我通过
窗口初始化网页。onload
,我必须按类名(
幻灯片
)找到一堆元素,并根据一些逻辑将它们重新分配到不同的节点。我有一个函数
Distribute(element)
,它接受一个元素作为输入并进行分发。我想做类似的事情(例如,如所述或所述):

var slides=getElementsByClassName(“幻灯片”);
对于(变量i=0;i
然而,这对我来说并不神奇,因为
getElementsByClassName
实际上并不返回数组,而是返回一个数组,它是

…这是我的猜测…

…在函数
Distribute
中更改(在此函数中更改DOM树,并克隆某些节点)<代码>对于每个
循环结构也没有帮助

变量slides实际上是不确定的,通过每次迭代它都会改变元素的长度和顺序

在我的例子中,迭代节点列表的正确方法是什么?我正在考虑填充一些临时数组,但不知道如何填充

编辑: 我忘了提到的一个重要事实是,可能有一张幻灯片在另一张幻灯片中,这实际上改变了
slides
变量,正如我刚刚发现的,这要感谢用户


我的解决方案是首先将每个元素克隆到一个数组中,然后将数组ono逐个传递到
Distribute()

根据MDN,从
节点列表中检索项的方法是:

nodeItem = nodeList.item(index)
因此:

var slides=document.getElementsByClassName(“幻灯片”);
对于(变量i=0;i
我自己也没有尝试过(正常的
for
循环对我来说一直都很有效),但是试一下。

我按照的建议反向循环,因为它是一个活动的
节点列表。以下是我为那些好奇的人所做的

  var activeObjects = documents.getElementsByClassName('active'); // a live nodeList

  //Use a reverse-loop because the array is an active NodeList
  while(activeObjects.length > 0) {
    var lastElem = activePaths[activePaths.length-1]; //select the last element

    //Remove the 'active' class from the element.  
    //This will automatically update the nodeList's length too.
    var className = lastElem.getAttribute('class').replace('active','');
    lastElem.setAttribute('class', className);
  }

您可以始终使用数组方法:

var slides = getElementsByClassName("slide");
Array.prototype.forEach.call(slides, function(slide, index) {
    Distribute(slides.item(index));
});

如果使用新的querySelectorAll,则可以直接调用forEach

document.querySelectorAll('.edit').forEach(function(button) {
    // Now do something with my button
});
请参见下面的评论。节点列表没有forEach函数。

如果与babel一起使用,您可以添加
Array.from
,它将非节点列表转换为forEach数组
Array.from
在以下浏览器(包括IE 11)中无法正常工作

Array.from(document.querySelectorAll('.edit')).forEach(function(button) {
    // Now do something with my button
});
在昨晚的会议上,我发现了另一种处理没有forEach的节点列表的方法

[...document.querySelectorAll('.edit')].forEach(function(button) {
    // Now do something with my button
});

显示为节点列表

显示为数组


第一
第二
函数myFunction(p){
var x=document.getElementsByClassName(“类名”);
var i;
对于(i=0;i对于(var i=0;i我在迭代中遇到了类似的问题,我在这里登陆了。也许其他人也在犯我犯的同样的错误

在我的例子中,选择器根本不是问题。问题是我把javascript代码弄乱了: 我有一个循环和一个子循环。子循环也使用了
I
作为计数器,而不是
j
,因此,因为子循环覆盖了主循环的
I
的值,所以这个循环从未进入第二次迭代

var dayContainers = document.getElementsByClassName('day-container');
for(var i = 0; i < dayContainers.length; i++) { //loop of length = 2
        var thisDayDiv = dayContainers[i];
        // do whatever

        var inputs = thisDayDiv.getElementsByTagName('input');

        for(var j = 0; j < inputs.length; j++) { //loop of length = 4
            var thisInput = inputs[j];
            // do whatever

        };

    };
var dayContainers=document.getElementsByClassName('day-container');
对于(var i=0;i
2021年的最新答案

当问到这个问题时(2013),
.getElementsBy*
方法返回了一个。然而,2021年的情况并非如此,所有这些DOM遍历方法都返回了一个活动的

这两个列表之间有着显著的差异。HTMLCollection有两个方法,而NodeList有五个方法,包括
NodeList.forEach
,它们可以用来迭代NodeList

Live collection是有问题的,因为无法在后台更新集合。为了实现可靠的集合,在当前的每个HTMLCollection实现中,每次访问集合时都会遍历DOM。实际上,这意味着每次访问Live collection的成员时(包括长度),浏览器遍历整个文档以查找特定元素

说:

如果集合是活动的,则该对象上的属性和方法必须对实际的基础数据而不是数据的快照进行操作

永远不要迭代实时HTMLCollection! 相反,将集合转换为数组,并迭代该数组。或者更确切地说,使用获取元素,这为您提供了一个静态节点列表和一种更灵活的选择元素的方法

如果您确实需要一个活动的元素列表,请使用最接近的公共祖先元素作为上下文,而不是
文档


值得注意的是,也存在live NodeList。live NodeList的一个例子是。

这实际上就是这样做的,所以你一定把其他事情搞糟了。
Distribute()
函数太长太复杂了,无法在这里复制,但我确信我正在更改内部的DOM结构,我也在复制(克隆)元素。当我调试它时,我可以看到变量
slides
每次在内部传递时都会更改。它不会更改,除非您在某个地方实际更改它。我相信
[...document.querySelectorAll('.edit')].forEach(function(button) {
    // Now do something with my button
});
 <!--something like this--> 
<html>
<body>



<!-- i've used for loop...this pointer takes current element to apply a 
 particular change on it ...other elements take change by else condition 
-->  


<div class="classname" onclick="myFunction(this);">first</div>  
<div class="classname" onclick="myFunction(this);">second</div>


<script>
function myFunction(p) {
 var x = document.getElementsByClassName("classname");
 var i;
 for (i = 0; i < x.length; i++) {
    if(x[i] == p)
    {
x[i].style.background="blue";
    }
    else{
x[i].style.background="red";
    }
}
}


</script>
<!--this script will only work for a class with onclick event but if u want 
to use all class of same name then u can use querySelectorAll() ...-->




var variable_name=document.querySelectorAll('.classname');
for(var i=0;i<variable_name.length;i++){
variable_name[i].(--your option--);
}



 <!--if u like to divide it on some logic apply it inside this for loop 
 using your nodelist-->

</body>
</html>
var dayContainers = document.getElementsByClassName('day-container');
for(var i = 0; i < dayContainers.length; i++) { //loop of length = 2
        var thisDayDiv = dayContainers[i];
        // do whatever

        var inputs = thisDayDiv.getElementsByTagName('input');

        for(var j = 0; j < inputs.length; j++) { //loop of length = 4
            var thisInput = inputs[j];
            // do whatever

        };

    };