0

In the code below, there are two functions, the outer function, and the inner IIFE function.

The output for the code below is:

outer func:  this.foo = bar
outer func:  self.foo = bar
inner func:  this.foo = undefined
inner func:  self.foo = bar

I do not understand why in the inner IIFE function, this cannot be used to access the foo variable while self still can. I understand that var self is a global varible for the inner function and can still be accessed. But what about this ?

var myObject = {
    foo: "bar",
    func: function() {
        var self = this;
        console.log("outer func:  this.foo = " + this.foo);
        console.log("outer func:  self.foo = " + self.foo);
        (function() {
            console.log("inner func:  this.foo = " + this.foo);
            console.log("inner func:  self.foo = " + self.foo);
        }());
    }
};
myObject.func();
Mozein
  • 787
  • 5
  • 19
  • 33

2 Answers2

5

In the inner function, this can be referenced, but it has a different value than in the outer function. Every function call involves setting up this for that particular call inside the called function. Note that it's every function call that determines this; it's not about the inherent nature of the function, it's about how a function is called.

In this case, the anonymous inner function is called without any explicit value for this, so its value will be a reference to the global object (window in a browser). In "strict" mode, the value would be undefined.

You could force this to be self:

    (function() {
        console.log("inner func:  this.foo = " + this.foo);
        console.log("inner func:  self.foo = " + self.foo);
    }.call(self));

By using .call(), the explicit value for this inside the anonymous function assures that it will reference the same object.

Pointy
  • 405,095
  • 59
  • 585
  • 614
1

Every function can have a different value of this, regardless of nesting, when it ends up being called. That is unless the function has been previously bound, which sets this to a particular value. In this case, the inner function is not part of a prototype, not called or bound to an object, so this will default back to window (or more correctly termed self).

You can resolve that in a few ways:

  1. Call the inner function with a scope, using }.call(this) instead of }(). This will explicitly provide the scope you want.

  2. Use closure to capture self (poorly named, since there is a global property with the same name) and use that in place of this.

ssube
  • 47,010
  • 7
  • 103
  • 140
  • This is confused on a number of levels. A function does not "have its own this". `this` attaches to an **invocation** of a function, not the function itself. A function cannot "be previously bound"; I guess you are referring to the act of creating a new function which calls an original function with a particular `this`. –  Apr 22 '15 at 15:10
  • @torazaburo The first part could use some clarification: every function, when invoked, can have a different value for `this` regardless of nesting. However, on the second point, a function absolutely *can* be previously bound. What do you think `bind` returns? It's a function that has been bound to a particular value of `this` at some point in the past and can be reused. – ssube Apr 22 '15 at 15:12
  • @ssube `.bind()` returns a *new function* - the original function isn't changed. That new function can itself be invoked with any value for `this`; it just happens to ignore it. – Pointy Apr 22 '15 at 15:15
  • @ssube Well, actually not. It is not correct to say "the function returned by `bind` is bound to a particular value of `this`, unless one is using the term "bind" loosely. What `bind` does is to return a function whose inner logic is to invoke an original function with a particular `this`. There is no formal notion of a "bound function". For instance, functions have no field or something which specifies some binding. See http://stackoverflow.com/questions/26545549/chaining-bind-calls-in-javascript-unexpected-result/26547029#26547029. –  Apr 22 '15 at 15:20