Understanding JavaScript this with private function and self executing function

197 views Asked by At

I was reading Angus Croll understanding JS this blog and found this

var a = {
  b: function() {
    var c = function() {
      return this;
    };
    return c();
  }
}; 

a.b();//window

To me it looks like, at the time of invoking c, c was inside b. that should be the invoking context (correct me, if i am wrong). when it executes, Why context(this) of c() is window?

there is another example i found in that blog

var a = {
  b: function() {
    return (function() {return this;})();
  }
};

a.b(); //window

why context of b is window? Does anonymous function always run in the global context?

2

There are 2 answers

1
Michael Geary On

Here's a good way to understand this (pun intended):

The value of this inside a function is determined by the way the function is called. With one exception, it doesn't have to do with where the function is defined, what other functions it may be nested inside, what object it was defined as part of, what kind of function it is, or any of that.

When you call a function using a method call like foo.bar() or foo[bar](), this inside the function is the foo object.

When you call a function with an ordinary function call like foo(), this in the function is the window object, or if the function uses strict mode it is undefined.

That's the one exception - if the function itself or its surrounding code has "use strict"; it changes this for a plain function call. For good code that shouldn't make a difference - you shouldn't be writing code that depends on this being the window object anyway.

Otherwise, what you care about is what object this refers to in a method call. And that's always determined by how the function is called, not how it's defined.

Let's go through your first example.

When you call a.b(), you're calling b as a method of the a object. So inside the b function, this is the same as a.

As it happens, it doesn't do us any good to know that, because the b function never does anything with this. All it does is call c() as an ordinary function. So inside c, this is the window object, or it would be undefined if you were in strict mode.

The c function simply returns its this value, or window. And that is also the return value from b. So that's why you see window as the result: it all comes from how the code calls the b and c functions.

Now about the second example: well, that's just terribly obfuscated code, isn't it? Who would ever write this code and expect anyone to understand it at first glance?

So let's turn it into a more readable form. This line is the problem:

    return (function() {return this;})();

Let's take out the parenthesized function expression:

    (function() {return this;})

and assign it to a temp variable:

    var temp = (function() {return this;});

We don't need the extra parentheses any more, and let's indent the code for readability:

    var temp = function() {
        return this;
    };

and we can call that temp variable as a function in the return statement:

    return temp();

Now we can put this back into the b function in the code example:

var a = {
  b: function() {
    var temp = function() {
        return this;
    };
    return temp();
  }
};

a.b(); //window

Hey! Doesn't that code look familiar? In fact, it's identical to the first example except for the name of the temp variable. So now you see why it works the same as the first one.

0
carpeliam On

One key to look for is the new keyword, which establishes a new context. Don't see a new? Then the context hasn't changed, which means this hasn't changed. If you called this from within window, then that's your context, and that's your this. (This changes if you use call() or apply() with a scope, but that obviously doesn't apply here.)