1

this should refer the object itself but in the following code why it's behaving differently?

var x   = 4,
    obj = {
        x: 3,
        bar: function() {
            var x = 2;
            setTimeout(function() {
                var x = 1;
                alert(this.x);
            }, 1000);
        }
    };
obj.bar();

Why the alert is 4 instead of 3?

Pranav C Balan
  • 113,687
  • 23
  • 165
  • 188
Mukesh Biswas
  • 63
  • 3
  • 8
  • 1
    Because `this` refers to the global object – philipp Jun 11 '16 at 06:36
  • Related: [How to access the correct `this` / context inside a callback?](http://stackoverflow.com/q/20279484/218196). MDN also has a section about `this` in the [`setTimeout` documentation](https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout#The_this_problem). – Felix Kling Jun 11 '16 at 06:49

1 Answers1

7

Inside setTimeout callback this refers to window object, so it's retrieving variable defined in global context.

You can make it working by binding the this context using Function#bind method .

var x = 4,
  obj = {
    x: 3,
    bar: function() {
      var x = 2;
      setTimeout(function() {
        var x = 1;
        alert(this.x);
      }.bind(this), 1000);
    }
  };
obj.bar();

Or use a local variable to cache the reference to this and use that inside callback function.

var x = 4,
  obj = {
    x: 3,
    bar: function() {
      var x = 2,
        that = this;
      setTimeout(function() {
        var x = 1;
        alert(that.x);
      }, 1000);
    }
  };
obj.bar();

Also refer the MDN documentation : The "this" problem

Pranav C Balan
  • 113,687
  • 23
  • 165
  • 188
  • I see the line: var that = this; all over the code base I work in. Your answer makes me wonder, what are the trade offs between bind vs. that? – James Collier Jun 11 '16 at 07:47
  • @JamesCollier : check the docs : ___[`The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind)___ – Pranav C Balan Jun 11 '16 at 07:48
  • I understand, but performance-wise, how does using .bind differ from caching this in a variable? – James Collier Jun 11 '16 at 07:50
  • @JamesCollier : both of them can be used... I don't know which one is better.... – Pranav C Balan Jun 11 '16 at 07:51
  • @JamesCollier : I think caching may be better that you can use anywhere with no more complexity... otherwise you need to bind each case if multiple functions are there... – Pranav C Balan Jun 11 '16 at 07:55