1

I have a doubt with javascript 'this'. I understand that 'this' refers to the object of the calling function. In example 1, if we are calling obj.bar(), why this.x = 4

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

Output: 4

And in the following code, why this.x =3 and 1 later:

var x = 3;
var foo = {
    x: 2,
    baz: {
        x: 1,
        bar: function() {
            return this.x;
        }
    }
}
var go = foo.baz.bar;
alert(go());
alert(foo.baz.bar());

Output: 3,1

1
  • It's because you're calling it inside another function (the one that is passed to setTimeout). Commented Oct 2, 2017 at 2:40

2 Answers 2

3

When you declare a variable at the very top level, you are creating a global variable in the window object. The keyword this at the top level refers to window.

var x = 4; // same as `window.x = 4`;
console.log(x); // same as `console.log(this.x)`;

When you call obj.bar(), the this keyword refers to obj inside of bar. But inside setTimeout you have a different this, the one that refers to the caller of the callback that you pass to setTimeout. This caller doesn't specify a value for this, so instead it just becomes the window object. Therefore, in this code:

setTimeout(function() {
   var x = 1;
   alert(this.x);
}, 1000);

this.x is the same as window.x, which is 4 as you defined it above in the global scope.

Addressing your second example, when you assign a function to a variable you lose the context of where that function came from:

var go = foo.baz.bar;

Now when you call go() notice there is no dot in that call, which means there is no explicit object access, which means there is no implicit this. In this case you can still pass this by using call:

// outputs `3` because `this` is `window`, and `window.x` is `3`
// as declared in the global scope
alert(go());

// Will output `2` because `this` is `foo`
alert(go.call(foo));

// Will output `1` because `this` is `foo.baz`
alert(go.call(foo.baz));

// Will output `1` because the implicit value of `this` is `foo.baz`
// since we have an explicit object access in this function call
alert(foo.baz.bar());

You can avoid many of these issues with use strict. In strict mode, this will be undefined when not explicitly or implicitly defined, instead of defaulting to the window object.

Sign up to request clarification or add additional context in comments.

Comments

3

this is not determined when creating the function. It's determined when invoking the function.

In the case of setTimeout, the function is just being executed out of the blue, once a certain amount of time has elapsed. There is no context, so the browser invokes the function in the global context. You happen to have declared a global variable of x=4, so that's what this.x will equal. If you used strict mode (by adding "use strict"; to the top of the script), then this would be undefined for the setTimeout case and you would get an error.

When you call go(), you have a standalone function with no context, so it's again being invoked in the global context. This results in it using your global x=3.

When you call foo.baz.bar(), you finally have a context. The context is foo.baz, so that's what this refers to, making this.x the equivilent of foo.baz.x, which equals 1.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.