Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why nested local function binds `this` to window instead of the parent

I was reading some documentation about javascript and stumbled upon the following code example:

var o = {
  value: 1,
  outer: function () {
    var inner = function () {
      console.log(this);  //bound to global object
    };
    inner();
  }
};
o.outer();

It outputs window.

I cannot figure out why is the this keyword bound to the global object (window) instead of the parent object (outer).
If you want to access outer from inner's scope, you have to pass the outer's this (which is just like passing outer itself) to its local inner function as an argument. So, as expected:

var o = {
  value: 1,
  outer: function () {
    var inner = function (that) {
      console.log(that);  //bound to global object
    };
    inner(this);
  }
};
o.outer();

outputs outer.

Isn't it a bit of a nonsense that in outer's scope this is bound to the object itself (i.e. outer), while in the inner's scope, which is local to outer, this is re-bound to the global object (i.e. it overrides outer's binding)?


The ECMAScript specs states that when entering the execution context for function code if the «caller provided thisArg» is either null or undefined, then this is bound to the global object.

But the following:

var o = {
    outer: function () {
        var inner = function () {
            console.log('caller is ' + arguments.callee.caller);
        };
        inner();
    }
}

outputs the object outer itself:

caller is function () {
    var inner = function () {
        console.log('caller is ' + arguments.callee.caller);
    };
    inner();
}



On a side, but probably relevant, note:
In strict mode the first code snippet outputs undefined instead of window.

like image 463
Nadir Sampaoli Avatar asked Jun 12 '13 19:06

Nadir Sampaoli


People also ask

What does () => mean in JavaScript?

It's a new feature that introduced in ES6 and is called arrow function. The left part denotes the input of a function and the right part the output of that function.

What does nested mean in JavaScript?

Nested functions A function is called “nested” when it is created inside another function. It is easily possible to do this with JavaScript.

How does the this keyword work?

“This” keyword refers to an object that is executing the current piece of code. It references the object that is executing the current function. If the function being referenced is a regular function, “this” references the global object.

How would you change the reference of this within a function?

By default, "this" is a reference to the object on which a particular function is called (in JavaScript all functions are bound to an object). We can, however, use call() and apply() to change this binding at runtime.


1 Answers

This is because this is set when the function is run, not when it's defined.

For example:

var o = {
    func: function(){
        console.log(this);
    }
};

When you call o.func(), you are doing so in the context o, so it works as expected.

Now let's say you do this:

var f = o.func;
f();

This will not work as expected. This is because when you call f(), it doesn't have any context attached to it, so this will be window.

You can fix this by using .call to change the value of this.

var f = o.func;
f.call(o);  // sets `this` to `o` when calling it
like image 172
Rocket Hazmat Avatar answered Oct 22 '22 03:10

Rocket Hazmat