无法在JavaScript中迭代nodelist对象

时间:2015-08-08 13:23:27

标签: javascript

我有以下代码,我试图通过迭代Nodelist对象“dateDisabled”来点击事件处理程序。

 var datesDisabled= document.getElementsByClassName('Val disabledDate');
  console.log(datesDisabled.length);// this outputs 7

  var d;

  for(d=0; d<=datesDisabled.length; d++)
     {
       datesDisabled[d].onclick=function(e) { 
   // above lines throws error   "datesDisabled[d] undefined"
          return false;
         }

      }

我的问题是为什么这段代码显示错误“datesDisable [d]未定义”,即使length属性有值?我知道实现此目标的其他方法,但想知道此代码有什么问题。

3 个答案:

答案 0 :(得分:1)

你需要

for(d=0; d<datesDisabled.length; d++)

getElementsByClassName返回一个HTMLCollection, 0基于(即成员HTMLCollection的索引为0,1 ..., n - 1

答案 1 :(得分:0)

如何构建for循环link

for (var i = 0; i < 9; i++) {
 console.log(i);
 // more statements
}


var datesDisabled= document.getElementsByClassName('Val disabledDate');

for(var d = 0; d < datesDisabled.length; d++){
  datesDisabled[d].onclick = function(e){ 
    return false;
  }
}

答案 2 :(得分:0)

给出如下HTML:

<ul>
  <li class="demo">List-element 1</li>
  <li class="demo">List-element 2</li>
  <li class="demo">List-element 3</li>
  <li class="demo">List-element 4</li>
  <li class="demo">List-element 5</li>
</ul>

以下JavaScript将找到五个元素:

var demoElements = document.getElementsByClassName('demo');

&#13;
&#13;
var demoElements = document.getElementsByClassName('demo');
snippet.log('Number of "demoElements" found: ' + demoElements.length);
&#13;
script + p[style]::before {
  content: 'Snippet Log:';
  display: block;
  color: #999;
  border-bottom: 1px solid #999;
  margin-bottom: 0.5em;
}
script + p[style] {
  border: 1px solid #666;
  padding: 0.5em;
  border-radius: 1em;
  margin: 1em auto 0 auto;
}
&#13;
<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

<ul>
  <li class="demo">List-element 1</li>
  <li class="demo">List-element 2</li>
  <li class="demo">List-element 3</li>
  <li class="demo">List-element 4</li>
  <li class="demo">List-element 5</li>
</ul>
&#13;
&#13;
&#13;

但是,JavaScript在其数组中使用从零开始的索引,因此当NodeList的 length 5时,NodeList的第一个元素位于索引0,最后一个元素是索引4;更一般地,这可以解释为 n 元素的数组(或NodeList,HTMLCollection等)具有从索引 0 运行的元素索引 n - 1 (这对阵列也是如此,等等。)

以下内容可以清楚地说明这一点:

var haystack = [1, 2, 3, 4, 5];

for (var i = 0, len = haystack.length; i < len; i++) {
  console.log('Number ' + haystack[i] + ' found at index: ' + i);
}

&#13;
&#13;
var haystack = [1, 2, 3, 4, 5];

for (var i = 0, len = haystack.length; i < len; i++) {
  snippet.log('Number ' + haystack[i] + ' found at index: ' + i);
}
&#13;
script + p[style]::before {
  content: 'Snippet Log:';
  display: block;
  color: #999;
  border-bottom: 1px solid #999;
  margin-bottom: 0.5em;
}
script ~ p[style] {
  border: 1px solid #666;
  padding: 0.5em;
  margin: 0!important;
  border-top-width: 0;
  border-bottom-width: 0;
}
script ~ p[style]:first-of-type {
  border-radius: 1em 1em 0 0;
  border-top-width: 1px;
}
script ~ p[style]:last-of-type {
  border-radius: 0 0 1em 1em;
  border-bottom-width: 1px;
}
&#13;
<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
&#13;
&#13;
&#13;

在您发布的代码中,不是使用小于运算符(<)作为条件,而是使用小于或等于(<=);假设你的循环中的这个操作符同时评估 n-1 n (其中 n 是提供的NodeList中元素的数量)为true,您的循环尝试访问 n th array-element,如上所述,不存在(假设提供的NodeList中的 last 元素(或HTMLCollection,Array等))是索引 < EM> N-1 ;这导致您观察到的错误:

var haystack = [1, 2, 3, 4, 5];

for (var i = 0, len = haystack.length; i <= len; i++) {
  console.log('Number ' + haystack[i] + ' found at index: ' + i);
}

此循环的最后一次迭代返回错误(在Chrome / Windows 8.1中):

Number undefined found at index: 5

&#13;
&#13;
var haystack = [1, 2, 3, 4, 5];

for (var i = 0, len = haystack.length; i <= len; i++) {
  snippet.log('Number ' + haystack[i] + ' found at index: ' + i);
}
&#13;
script + p[style]::before {
  content: 'Snippet Log:';
  display: block;
  color: #999;
  border-bottom: 1px solid #999;
  margin-bottom: 0.5em;
}
script ~ p[style] {
  border: 1px solid #666;
  padding: 0.5em;
  margin: 0!important;
  border-top-width: 0;
  border-bottom-width: 0;
}
script ~ p[style]:first-of-type {
  border-radius: 1em 1em 0 0;
  border-top-width: 1px;
}
script ~ p[style]:last-of-type {
  border-radius: 0 0 1em 1em;
  border-bottom-width: 1px;
}
&#13;
<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
&#13;
&#13;
&#13;

这可以预见到,因为 n th 位置中没有数组元素。

所以,最简单的方法是简单地使用:

for (var index = 0, len = collection.length; index < len; i++)

或者:

for (var index = 0, len = collection.length; index <= len - 1; i++)

但是,为了易于编写,大多数人(包括我自己)在需要for循环时使用前者。

然而,在ECMAScript 5下,在兼容浏览器中更简单的方法是简单地使用Array.prototype.forEach()迭代数组:

[0, 1, 2, 3, 4].forEach(function (arrayElement, index, suppliedArray) {
  console.log(arrayElement + ' found at ' + index);
});

在循环提供的数组的forEach()方法中,匿名函数的参数自动提供,并且是:

  1. arrayElement:数组元素保存在我们正在迭代的数组的当前索引处,
  2. index:我们正在迭代的数组中的array-element的索引,
  3. suppliedArray:提供给forEach()方法的数组本身的副本。
  4. 现在,虽然forEach()方法(在那些支持它的浏览器中)用于迭代数组,但它不能直接用于NodeLists或HTMLCollections(或任何数组的数组) - 不使用Function.prototype.call()

    ,但不是数组

    &#13;
    &#13;
    var demoElements = document.getElementsByClassName('demo');
    
    Array.prototype.forEach.call(demoElements, function(demoElement) {
      demoElement.style.color = 'orange';
    })
    &#13;
    <ul>
      <li class="demo">List-element 1</li>
      <li class="demo">List-element 2</li>
      <li class="demo">List-element 3</li>
      <li class="demo">List-element 4</li>
      <li class="demo">List-element 5</li>
    </ul>
    &#13;
    &#13;
    &#13;

    Function.prototype.call()的使用允许我们将我们希望视为对象的对象分配(这里:demoElements作为第一个参数,第二个是匿名函数,它将被提供给Array.prototype.forEach()方法。

    参考文献: