Why IIFE this keyword refers to window object..?

2019-04-10 20:58发布

问题:

When I run the below code why the IFFE this refers to window object and not to a

var a = {
 printThis : function () {
 console.log('printThis', this);
  var inner = (function () {
    console.log('inner', this);
   })();
  }
};

a.printThis();

//output

printThis a object

inner window object <-- why..?

回答1:

Consider the following example:

var a = {};
var b = {};
a.hello = function() { console.log(this); };
b.hello = a.hello;

In most programming languages, b.hello() would print a since they base this on where the function is. The function is in a, so this is a. Makes sense, right?

However, JavaScript is a bit different in that regard. Instead of where it is, it's based on how it was called. b.hello() calls hello on b, thus this is set to b. This also makes sense since JavaScript doesn't really have a concept of "where" a function is (unlike methods in, say, Java, which are always tied to a specific class), and it's hard to determine that a is where it "is".

So, foo.bar() will always set this to foo for the purposes of this call to bar (unless one has used bind or similar to bind this to a specific value in advance).

Now, an IIFE is invoked on... nothing, really. It's not a foo.bar() situation, it's just a bar() where bar is your function expression. In cases like this where there's no foo, it defaults to the window object.

There are two simple workarounds:

  1. Create a variable outside the IIFE containing the value you´re interested in: var that = this; and use that instead of this in the IIFE, or
  2. bind the this value: (function(){ CODE GOES HERE }).bind(this)();