0

var table = document.querySelectorAll(".numbers");

function seppuku() {
  for (let i in table) {
    table[i].style.color = "red";
  }
}
seppuku();
<div class="numbers">1</div>
<div class="numbers">2</div>
<div class="numbers">3</div>

So here's my code. My problem is: Why console.log communicate "Cannot set property 'color' of undefined" after seppuku() function invoking?

It's not like var table is not defined! Actually, it has global scope and should be available for 'for.. in' loop. Moreover, this function works, chosen elements has color: red property now. How that works despite the communicate in console?

programtreasures
  • 4,250
  • 1
  • 10
  • 29
  • 1
    https://stackoverflow.com/questions/500504/why-is-using-for-in-with-array-iteration-a-bad-idea - [watch the output when you log `table[0]` to the console](https://jsfiddle.net/38m95eok/2/). – Andy Feb 21 '18 at 12:26
  • 1
    Instead of for-in loop use for loop – Kiran Shinde Feb 21 '18 at 12:26
  • 1
    Try to `console.log(table)` and you'll understand what your loop is iterating – Jeremy Thille Feb 21 '18 at 12:30
  • because the result of `document.querySelectorAll(".numbers")` it's an array like object,if you would use the for loop you must convert to array `var table = document.querySelectorAll(".numbers");` `table = Array.prototype.slice.call(table)` see https://fiddle.jshell.net/fe23Lr42/1/ – Taha Azzabi Feb 21 '18 at 12:37

3 Answers3

3

You used for...in statement which iterates over the enumerable properties of an object. In this case, table object contains following enumerable properties.

{
  "0": <div class="numbers">1</div>,
  "1": <div class="numbers">2</div>,
  "2": <div class="numbers">3</div>,
  "length": 3,
  "item": function item() { [native code] },
  "entries": function entries() { [native code] },
  "forEach": function forEach() { [native code] },
  "keys": function keys() { [native code] },
  "values": function values() { [native code] }
}

So in the 4th iteration, i becomes length and table['length'].style throws an error. We can use forEach method to resolve this issue.

var table = document.querySelectorAll(".numbers");

(function seppuku() {
   table.forEach(function(item) {
   item.style.color = "red";
   });
})();
<div class="numbers">1</div>
<div class="numbers">2</div>
<div class="numbers">3</div>
fyasir
  • 2,924
  • 2
  • 23
  • 36
0

Using let i in table has last element for i as length so it results to table['length'].style.color = "red"; which is incorrect as there is no element table['length'] and returns undefined. Better way is to just loop through the length of table which will be 0, 1 and 2.

var table = document.querySelectorAll(".numbers");

function seppuku() {
  for (var i=0; i<table.length; i++) {
    table[i].style.color = "red";
  }
}
seppuku();
<div class="numbers">1</div>
<div class="numbers">2</div>
<div class="numbers">3</div>
Ankit Agarwal
  • 30,378
  • 5
  • 37
  • 62
  • Thank you. I've just wanted to get deeper into ES6 (I knew typical "for loop" method). But, yeah, definitely I'll use working one ;) – Daniel Jackowiak Feb 21 '18 at 12:38
0

Use the simple for loop instead of for..in

<!DOCTYPE html>
<html>
<body>

<div class="numbers">1</div>
<div class="numbers">2</div>
<div class="numbers">3</div>

<script>

function seppuku() {

var table = document.querySelectorAll(".numbers"); 
  for (let i=0;i<table.length;i++ ) {
   
    table[i].style.color = "red";
  }
}
seppuku();
</script>

</body>
</html>
Vasim Hayat
  • 909
  • 11
  • 16