0

I have this code that fails when I try to use the for loop

class TestA {
  testArray = [];
  constructor() {
    this.testArray.push({
      name: "joe",
      age: 70
    });
    this.testArray.push({
      name: "mike",
      age: 50
    });
    this.testArray.push({
      name: "bob",
      age: 33
    });
  }
  testLoop() {
    for (test of this.testArray) {
      console.log(" >>> " + test.name + " " + test.age);
    }
  }
}
var a = new TestA();
a.testLoop();

The error:

Uncaught ReferenceError: test is not defined

I can get away with that by using different kind of loop but don't understand why that doesn't work?

j08691
  • 204,283
  • 31
  • 260
  • 272
Coder547
  • 119
  • 9
  • 2
    `for (const test of this.testArray)` – Yury Tarabanko Jul 15 '20 at 16:24
  • 1
    Maybe change `test of` to `let test of`? – evolutionxbox Jul 15 '20 at 16:24
  • It should be :```for (let test of ....)``` – Praveen Dass Jul 15 '20 at 16:26
  • 1
    I'd point out that you don't need multiple, consecutive calls to `.push()`. Just add all the objects as arguments to a single call, and they all get added to the array. `this.testArray.push({...}, {...}, {...})` –  Jul 15 '20 at 16:28
  • thanks for your answers I am new to JS and had not heard of let before. Also this kind of loop only fails when used inside class function (at least in my experience) – Coder547 Jul 15 '20 at 16:34
  • 1
    @Coder547: I think inside a `class` definition, you're running in *strict mode*, which sets more stringent requirements. Outside `class` you can manually put your code into that mode by using the `"use strict"` declarative. –  Jul 15 '20 at 16:38

4 Answers4

3

You forgot to declare test using let or const.

Use const if you want the identifier within the loop body to be read-only (so that, for instance, if someone modifies the code later to add an assignment, it's a proactive error in strict mode). Use let if you want to be able to assign to it (because you have an assignment in your code, or you want someone to be able to add one later without changing the declaration).

Extracted from: for...of loop. Should I use const or let?

class TestA {
  testArray = [];
  constructor() {
    this.testArray.push({
      name: "joe",
      age: 70
    });
    this.testArray.push({
      name: "mike",
      age: 50
    });
    this.testArray.push({
      name: "bob",
      age: 33
    });
  }
  testLoop() {
    for (let test of this.testArray) {
      console.log(" >>> " + test.name + " " + test.age);
    }
  }
}
var a = new TestA();
a.testLoop();
Tu.Ma.
  • 1,325
  • 10
  • 27
2

You should write let for the line:

for (let test of this.testArray) {
1

In a for..of statement you need to declare your loop variable (test) with const, let, or var:

class TestA {
  testArray = [];
  constructor() {
    this.testArray.push({
      name: "joe",
      age: 70
    });
    this.testArray.push({
      name: "mike",
      age: 50
    });
    this.testArray.push({
      name: "bob",
      age: 33
    });
  }
  testLoop() {
    for (let test of this.testArray) {
      console.log(" >>> " + test.name + " " + test.age);
    }
  }
}
var a = new TestA();
a.testLoop();
j08691
  • 204,283
  • 31
  • 260
  • 272
0

Bind the function in the constructor, as the this is not preserved.

class TestA {
  testArray = [];
  constructor() {
    this.testArray.push({
      name: "joe",
      age: 70
    });
    this.testArray.push({
      name: "mike",
      age: 50
    });
    this.testArray.push({
      name: "bob",
      age: 33
    });
    
    this.testLoop = this.testLoop.bind(this);
  }
  testLoop() {
    for (const test of this.testArray) {
      console.log(" >>> " + test.name + " " + test.age);
    }
  }
}
var a = new TestA();
a.testLoop();
Kunal Mukherjee
  • 5,775
  • 3
  • 25
  • 53
  • This is completely unrelated and not necessary in the OP's case. – Yury Tarabanko Jul 15 '20 at 16:28
  • @YuryTarabanko But he's trying to refer to `this.testArray` right, which will be undefined – Kunal Mukherjee Jul 15 '20 at 16:30
  • It wont. He is using this method like `a.testLoop()` so it will have `a` as a context. You could try it. The only problem was that OP hadn't declared loop variable and class body is evaluated in strict mode. – Yury Tarabanko Jul 15 '20 at 16:32
  • If `a.testLoop()` didn't properly set `this` to the `a` object, that would make methods almost useless. You'd need to bind it if you're going to separate the method from the object before invoking it. –  Jul 15 '20 at 16:32