简体   繁体   English

Javascript:每次for循环迭代时,数组的大小都会减小。 为什么?

[英]Javascript: The size of my array decreases with each for-loop iteration. Why?

I am attempting to change the classname of three elements that have the same classname. 我试图更改具有相同类名的三个元素的类名。 However, when i iterate through my for-loop array the size of the array decreases with each iteration. 但是,当我遍历for循环数组时,数组大小随每次迭代而减小。 As a result, I am unable to change the classname of all three elements. 结果,我无法更改所有三个元素的类名。 Please can some one advise. 请可以给个建议。 I am at a total loss. 我完全不知所措。

javascript JavaScript的

 var i;

 for(i=0; i < toAssignArray.length; i++){
        console.log('size of aaray: '+ toAssignArray.length);
        console.log('id in array ['+ i +']: ' + toAssignArray[i].id);

        toAssignArray[i].className = 'toAssignOff';

        console.log('className of ['+i+']' + toAssignArray[i].className);

            }

HTML HTML

 <div id="toAssign_thanhphan_618" class="toAssign" onclick="pcoment.assignThisAuthor('thanhphan', 'reply_618', '740')" style="display: inline;">Assign Comment</div>

 <div id="toAssign_jimmywhite_618" class="toAssign" onclick="pcoment.assignThisAuthor('jimmywhite', 'reply_618', '740')">Assign Comment</div>

 <div id="toAssign_anquoc_618" class="toAssign" onclick="pcoment.assignThisAuthor('anquoc', 'reply_618', '740')">Assign Comment</div>

console 安慰

[Log] size of aaray: 3 (pub_comments.js, line 604)
[Log] id in array [0]: toAssign_thanhphan_618 (pub_comments.js, line 606)
[Log] className of [0]toAssign (pub_comments.js, line 610)
[Log] size of aaray: 2 (pub_comments.js, line 604)
[Log] id in array [1]: toAssign_anquoc_618 (pub_comments.js, line 606)

You don't have an array, you have a NodeList . 您没有数组,但是有一个NodeList From many DOM APIs, NodeList instances are live , which means they change dynamically when the elements in them change. 在许多DOM API中,NodeList实例是live的 ,这意味着它们中的元素更改时它们会动态更改。 If you do a .getElementsByClassName() for example, if you change an element in the list such that it no longer has the class name in question, it immediately vanishes from the list. 例如,如果执行.getElementsByClassName() ,则如果更改列表中的元素,使其不再具有相关的类名,则该元素将立即从列表中消失。

There are two ways to handle this. 有两种方法可以解决此问题。 First, you can turn the NodeList into a real array. 首先,您可以将NodeList转换为真实数组。 In modern (ES2015) JavaScript, that's super-easy: 在现代(ES2015)JavaScript中,这非常简单:

var realArray = Array.of(nodeList);

In ES5, it's not much harder: 在ES5中,这并不困难:

var realArray = Array.prototype.slice.call(nodeList, 0);

The second alternative is to iterate through the list differently. 第二种选择是对列表进行不同的迭代。 Instead of using a for loop with an index variable, use a while loop and only operate on the first element: 代替使用带索引变量的for循环,而使用while循环并仅对第一个元素进行操作:

while (nodeList.length) {
  nodeList[0].className = ""; // or whatever
}

Of course that only works if what you're doing is always going to remove the element from the list. 当然,只有在您始终要从列表中删除元素的情况下,此方法才起作用。 If not, then I prefer using the "real array" approach. 如果没有,那么我更喜欢使用“真实数组”方法。

I guess a fifth third alternative would be to use a different API, one that doesn't return a live NodeList. 我猜 第五种 选择是使用其他API,即返回实时NodeList的API。 The .querySelectorAll() function is a general-purpose API that finds DOM nodes but doesn't return a live list (it's still a NodeList, but it's not live). .querySelectorAll()函数是一个通用API,可查找DOM节点,但不返回活动列表(它仍然是NodeList,但不是活动列表)。 So instead of .getElementsByClassName() you'd use 因此,您可以使用.getElementsByClassName()代替

var nodeList = document.querySelectorAll(".the-class-name");

通过更改节点列表来解决迭代的另一种标准方法是向后循环:

  for(i=toAssignArray.length-1 ; i >=0; i--){...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM