先直接给出结论:在非严格模式下,IIFE (立即执行函数表达式)内部的 this 指向全局对象(浏览器环境中即为 window)。这一现象与“立即执行”的语法形式本身无关,其根本原因在于 JavaScript 底层的默认绑定规则发挥了作用——当函数被独立调用且未附带任何显式上下文时,this 会自动挂载到全局对象上。这一底层机制,才是真正的幕后推手。

很多人认为“谁调用,this 就指向谁”,但现实是:当没有显式指定调用者时,JavaScript 必须有一个兜底方案。这个兜底方案正是默认绑定。它仅在函数以“简单调用”的形式出现时才会被触发:
- 不是作为对象方法调用(例如
obj.fn()这种形式) - 不是通过
call/apply/bind显式指定 this - 不是作为构造函数使用(
new fn()) - 也不是箭头函数(箭头函数本身不绑定
this,而是继承自外层作用域)
当满足这些条件时,JavaScript 引擎会严格按照规则执行:非严格模式下,this 被设置为全局对象;严格模式下,则被设置为 undefined。
IIFE 的写法通常如下:
(() => { console.log(this); })();
尽管外部包裹了括号,但在执行时仍然是“直接调用”——没有点号操作、没有 call、没有 new,因此触发了默认绑定。原理就是这么简单。
为什么 IIFE 看似“有主语”,实则没有?
有人可能会误以为 (function(){...})() 中的括号“属于”函数本身,从而认为应该存在一个调用上下文。但从语法角度来看,外层括号仅仅是分组操作符,其作用是为了消除函数声明与调用之间的歧义,并不会创建任何调用上下文。换句话说,它与下面这段代码本质上是相同的:
const f = function(){ console.log(this); };
f(); // 同样是默认绑定
IIFE 只是将定义和调用压缩到了一行代码中,本质并未发生改变。
严格模式下 this 为 undefined,不是 bug,而是默认绑定的另一面
一旦开启了严格模式,默认绑定便不再兜底到全局对象:
(function(){ "use strict"; console.log(this); })(); // undefined
这个现象恰恰印证了底层原理:默认绑定是一条明确清晰的规则,而并非“总是指向 window”。其具体行为取决于代码是否处于严格模式之下。
想让 IIFE 里的 this 指向其他对象?可以,但需要手动干预
默认绑定的优先级其实并不高,完全可以被更高优先级的绑定方式所覆盖:
- call/apply/bind:
(function(){ console.log(this); }).call({x:1});→ 输出{x:1} - 箭头函数:它本身不绑定
this,而是沿着作用域链查找外层this(例如外层普通函数中的this) - 作为对象方法调用:虽然不算是 IIFE 的常见写法,但从技术上讲是可行的——
obj = { f: function(){ console.log(this); } }; obj.f();
需要特别注意的是,这些手法并非“IIFE 自身改变了 this”,而是你主动绕过了默认绑定规则。真正理解这一点,才算透彻掌握了 IIFE 中 this 的指向问题。
