为什么IIFE中的this关键字指向window对象..?

6
当我运行下面的IFFE时,为什么this关键字指的是window对象而不是a变量?
var a = {
 printThis : function () {
 console.log('printThis', this);
  var inner = (function () {
    console.log('inner', this);
   })();
  }
};

a.printThis(); 

以下是输出结果:
printThis **an object**

inner **window object**   <-- why..?

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

a.printThis();


你没有调用 a.inner(),只是调用了 inner()。因此 a 不会变成 this - Thilo
但它也在一个then语句中。 - Mr. A
1
每个函数都有自己的 this。如果您想保留外部的 this,则必须使用 bindvar self = this 或“fat arrow”。 - Thilo
你能否解释一下这对JavaScript引擎是如何工作的? - Mr. A
1
可能是[“this”关键字如何工作?]的重复问题(https://dev59.com/zHA75IYBdhLWcg3wv70j)。 - Thilo
显示剩余3条评论
1个回答

15

考虑下面的例子:

var a = {};
var b = {};
a.hello = function() { console.log(this); };
b.hello = a.hello;
在大多数编程语言中,b.hello()将会打印出a,因为它们基于函数所在的位置确定this。该函数在a中,因此thisa。听起来很有道理,对吧?
然而,在这方面,JavaScript略有不同。它的依据是调用方式,而不是所在位置b.hello()b上调用hello,因此this被设置为b。这也很有道理,因为JavaScript实际上没有“函数所在位置”的概念(与其他语言中的方法不同,比如Java,它们总是与特定类相绑定),很难确定a是它所在的位置。
因此,对于foo.bar(),为了这次对bar的调用,this将始终被设置为foo(除非事先使用bind或类似的方法将this绑定到特定值)。
现在,IIFE被调用时... 实际上什么都没有。这不是一个foo.bar()的情况,只是一个bar(),其中bar是函数表达式。在这种没有foo的情况下,默认为window对象。
有两个简单的解决方法:
1. 在IIFE之外创建一个变量来包含你感兴趣的值:var that = this; 并在IIFE中使用that代替this;或者 2. bind this的值:(function(){ CODE GOES HERE }).bind(this)();

在阅读这个答案之前,我正要因为沮丧而翻转桌子,但我甚至都不知道这是什么 - Scribblemacher

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接