This and setTimeout()

Can someone explain to me why

var Computer = function (type) {
    this.type = type;
};

Computer.prototype.run = function () {
    return this.type;
}

computer = new Computer('Windows');
computer.run();

returns “Windows”, yet when I add a delay:

var Computer = function (type) {
    this.type = type;
};

Computer.prototype.run = function () {
    setTimeout(function() { return this.type }, 500);
}

computer = new Computer('Windows');
computer.run();

I get undefined. My guess is that the this is the function() { } not the Computer object am I right or is something else going on here?

My guess is that the return value of Computer.prototype.run is implicitly undefined. All it does is sets a timeout.

If you console.log instead of return, it does the same thing.

If I understood it correctly, the callback to setTimeout is called with the global object as its context (like, 500ms later, it’s called like a normal function, and this is thus bound to the global object, which has no type variable. If it doesn’t make sense try declaring var type = 'hello'; at the top of the code)

You may have to .bind your callback

setTimeout( (function () {
  console.log(this.type);
} ).bind(this), 500);

or see this repl.it

1 Like

It is because, this no longer refers to the Computer instance.

EDIT: As @kevcomedia said. this seems to refer to the window object (since setTimeout is a function of the window object: window.setTimeout)

2 Likes

Maybe relevant:

2 Likes

also ch. 1 and ch. 2 from ‘You Don’t Know JS: this & Object Prototypes’ is a great explanation of how ‘this’ gets bound…

1 Like

your code basically does that :

function globalFunction(fn, delay){
  console.log(this); // javascript will look for the value of "this" and it's the global object
  console.log(this.type); // undefined
  fn(); // undefined
}

var Computer = function (type) {
    this.type = type;
};

Computer.prototype.run = function () {
    globalFunction(function() { return this.type }, 500);
}

computer = new Computer('Windows');
computer.run();

If you run your code in the browser and replace

setTimeout(function() { return this.type }, 500);

with

setTimeout(function() { return this.alert('test') }, 500);

You will see a pop-up, confirming that “this” is “window”.

1 Like