0

When I use the work method in the doTasks method, I get the error "Uncaught TypeError: Cannot read property 'work' of undefined". I don't exactly understand what is going on.

class Employee {
    constructor(name) {
    this.name = name;
    this.totalWorktime = 0;
  }

  work(worktime) {
    this.totalWorktime += worktime;
  }

  doTasks(tasks){
    tasks.forEach(function(element) {
      this.work(element);
   });
  }
}
H. Low
  • 16
  • 3
  • 2
    use `let $this = this;` above your forEach and use it like this `$this.work` – Get Off My Lawn May 20 '17 at 22:18
  • 1
    This is why we have for...of. To avoid the consequences of having unnecessary callbacks. – Estus Flask May 20 '17 at 22:32
  • Normally I'd use an arrow function for this – Ray May 20 '17 at 22:34
  • [`.forEach()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach?v=example) has a 2nd parameter specifically for controlling the value of `this` inside the iterator function. – `tasks.forEach(function () { ... }, this);` – Jonathan Lonowski May 20 '17 at 22:51
  • Most people here recommend the arrow function, which works perfectly in this example. But can you always use them in more complex pieces of code? Or are you better off then with `let $this = this;` as suggested above? – H. Low May 21 '17 at 08:45

2 Answers2

3
doTasks(tasks) {
  tasks.forEach((element) => {
      this.work(element);
  });
}

remove the "function" so this is really "this"

UXDart
  • 2,500
  • 14
  • 12
1

You are in a different closure. Either use arrow notation (recommended)...

doTask(tasks) {
  tasks.forEach((element) => {
    this.work(element);
  });
}

...or create a reference to the class instance outside the loop.

doTasks(tasks) {
  let that = this;
  tasks.forEach(function(element) {
    that.work(element);
 });
}
Shane
  • 3,049
  • 1
  • 17
  • 18