IIFE的核心是通过函数创建独立词法作用域以隔离变量,标准写法为(function(){/*私有代码*/})();,配合揭示模块模式可暴露有限接口,支持传参注入依赖、启用严格模式及解决ES5循环闭包问题。

直接用 IIFE 包一层函数,就能把变量、函数关在里面,外部碰不到——这是 ES5 时代最可靠的作用域隔离手段。
核心写法与作用域边界
IIFE 的本质不是“立刻执行”,而是借函数创建新词法作用域。只要变量定义在函数体内,无论用 var、let 还是 const,都只在该函数内有效。
- 标准写法:(function() { /* 私有代码 */ })();
- 括号必须存在——它让 JS 把
function(){}当作表达式,而非声明;没括号会报语法错误 - 函数体内部声明的变量(如
var apiToken = 'xxx';)对外完全不可见,也不会挂到window上
封装模块并暴露有限接口
结合“揭示模块模式”(Revealing Module Pattern),可明确控制哪些内容能被外部使用。
- 在 IIFE 内部定义私有变量和工具函数
- 返回一个对象,只包含需要公开的方法或属性
- 外部只能通过返回对象访问,无法绕过直接读取私有状态
例如:
const Logger = (function() {const logs = [];
function format(msg) { return `[${new Date().toISOString()}] ${msg}`; }
return {
log: msg => { logs.push(format(msg)); },
count: () => logs.length
};
})();
调用
Logger.log('start') 没问题,但 Logger.logs 或 Logger.format 都是 undefined。
传参注入依赖与防压缩混淆
常见于老项目或 UMD 包装中,既保证环境安全,又便于压缩工具处理。
- 把
window、document等全局对象作为参数传入,避免多次查找和意外覆盖 - 压缩时,参数名可被重命名(如
w),但内部逻辑不变 - 严格模式建议加上:
'use strict';,防止意外创建全局变量
示例:
(function(global, doc) {'use strict';
const el = doc.getElementById('app');
global.renderApp = function() { /* ... */ };
})(typeof window !== 'undefined' ? window : globalThis, document);
应对循环闭包等经典陷阱
ES5 中 for (var i = 0; i < 3; i++) setTimeout(() => console.log(i), 0) 会输出三个 3。IIFE 可为每次迭代创建独立作用域。
- 把循环变量作为参数传进 IIFE,确保每次回调捕获的是当前值
- 写法:
for (var i = 0; i < 3; i++) (function(idx) { setTimeout(() => console.log(idx), 0); })(i); - 虽然后来
let能自然解决,但在仅支持 ES5 的运行时里,这是刚需

















