0

In this example

class Car {
    describe() {
        console.log("I have " + this.wheels);
    }

    testMe() {
        setTimeout( this.describe, 1000);
    }

    constructor(wheels) {
        this.wheels = wheels;
    }
}

let myCar = new Car(4);
myCar.testMe(); // I have undefined

How come the expected value of this isn't passed inside the describe function ?

edit : Can you confirm that is setTimeout was an arrow function, I wouldn't get undefined ?

Lev
  • 13,856
  • 14
  • 52
  • 84

1 Answers1

0

A bare function reference has no context, even if it was retrieved as a property of an object.

Within your testMe function you need either:

setTimeout(() => this.describe(), 1000);

or

setTimeout(this.describe.bind(this), 1000);

or

let self = this;
setTimeout(function() {
    self.describe();
}, 1000);

That last one could be written as an arrow function, of course, but if you're doing that you might as well use the first version, with no local copy of this required.

Regarding your edit, it is possible to pass just this.describe by making describe an arrow function, assigned from inside the constructor, but note that this then means that every instance of the object would have its own copy of that function instead of there just being a single copy on the prototype of the class:

constructor(wheels) {
    this.wheels = wheels;

    this.describe = () => {
        console.log("I have " + this.wheels);
    }
}
Alnitak
  • 334,560
  • 70
  • 407
  • 495
  • because without bind or call or apply it is equivalent to writing setTimeout( function() { console.log("I have " + this.wheels); }, 1000); – Lev Feb 09 '17 at 23:42
  • @Lev what's your point? The code you've written in that comment wouldn't work either. – Alnitak Feb 09 '17 at 23:45