JavaScript立即执行函数(IIFE)详解与实战应用
本文深入解析JavaScript中的立即执行函数(IIFE),涵盖其标准写法、多种表达式实现方式(如逻辑运算符、new关键字等)以及带参数的用法。通过经典面试题案例,展示如何利用IIFE结合闭包解决循环中的变量捕获问题,帮助开发者掌握创建独立作用域的技巧。
在JavaScript开发中,你可能会遇到一些特殊的函数定义方式,例如以下示例所示:

这类函数在浏览器加载页面时会自动执行,无需手动调用。此前在讲解闭包时也曾提及此类函数,通常被称为立即执行函数(Immediately Invoked Function Expression,简称IIFE)。
立即执行函数具备以下显著特征:
- 自动触发执行
- 仅执行一次
立即执行函数的基本格式
立即执行函数通常遵循以下标准格式:
# 格式一(//W3C 推荐这种写法)
(function (){
}())
#格式二 (但是这个才是最常用的方式之一)
(function (){
})();
从上述格式可以看出,立即执行函数通常不定义函数名。因为函数无需通过名称进行后续调用,这与使用字面量方式定义函数的作用类似,省略函数名更为简洁。
接下来,结合闭包概念与立即执行函数,通过一个具体示例进行说明:
var fun=(
function(){
function test(a,b){
console.log(a+b);
}
return test;
}
)()

立即执行函数的其他实现方式——表达式
虽然前文介绍了标准的立即执行函数格式,但还存在其他实现该功能的方法。例如以下代码并非采用标准格式:
!function(){
console.log("test");
}()

观察输出结果,第一行输出“test”,体现了立即执行函数的执行效果;第二行输出true,是因为前面添加了感叹号(!)。在之前的隐式转换讲解中提到,感叹号后的表达式会被强制转换为布尔类型。
这里产生了一个疑问:为什么这种方式能够实现立即执行的效果?
为了分析这种情况,我们先看一个普通的表达式函数:
var test=function(){
console.log("test表达式")
}
#这样声明后,如何使用呢?如下
test();

此时可以产生一个大胆的设想:如果给变量赋值的函数,通过“变量名+()”的方式即可执行,那么是否可以直接编写这样的结构?
var test=function(){
console.log("test表达式")
}()

由此可见,表达式函数也具备立即执行的效果。
(补充说明:之所以输出undefined,是因为该函数本身没有return语句,因此浏览器控制台会输出undefined。)
那么,是否可以直接在函数定义后紧跟括号来执行呢?
function(){
console.log("test表达式")
}()

结果显示,必须基于表达式的前提,才能在函数后添加括号(),否则会导致报错。
由此引发另一个大胆的想法:既然感叹号(!)能将函数转换为表达式函数,从而允许后续添加()直接运行,那么如果在函数前添加加号(+)会怎样?
+function(){
console.log("test表达式")
}()

既然加号可行,那么:
| + | - |
|---|---|
| ! | ~ |
当然,乘号和除号无法实现此效果。此外,还有一个神奇的关键字也能产生类似效果,那就是new和void。
new function(){
console.log("test表达式")
}()

另外,逻辑运算符||和&&也能实现这一功能。
不过,这需要根据其特性在前方添加真值或假值才能生效,单独使用是不行的。
1 && function(){
console.log("test表达式")
}()
或者
0 || function(){
console.log("test表达式")
}()

还有一个神奇的符号(逗号)也能实现此功能:
1,function(){
console.log("test表达式")
}()

可以看出,如果使用逗号,无论前面的表达式真假,都会执行后面的表达式函数。
立即执行函数支持参数传递
立即执行函数同样可以接收参数,具体示例如下:
(function(a,b){
console.log(a,b)
})(1,2)

应用场景
这是一个非常经典的面试题。首先创建一个HTML文件:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>test</title>
</head>
<body>
<ul id=”test”>
<li>这是第一条</li>
<li>这是第二条</li>
<li>这是第三条</li>
</ul>
<script>
var liList=document.getElementsByTagName('li');
for(var i=0;i<liList.length;i++)
{
liList[i].onclick=function(){
console.log(i);
}
};
</script>
</body>
</html>
目标是点击第几个li标签就输出对应的数字,但实际结果往往不符合预期。

这是因为在点击li元素时,for循环早已执行完毕。此前学习的let关键字也可以解决这个问题。
var liList=document.getElementsByTagName('li');
for(let i=0;i<liList.length;i++)
{
liList[i].οnclick=function(){
console.log(i);
}
};

虽然let可以解决该问题,但并未使用立即执行函数。当然,也可以通过立即执行函数来进行修改。
var liList=document.getElementsByTagName('li');
for(let i=0;i<liList.length;i++)
{ (function(a){
liList[a].οnclick=function(){
console.log(a);
}
})(i)
};

可以看出,立即执行函数会形成自己的封闭空间,不受外部其他变量的影响。如果在此基础上添加return语句,就是一个标准的闭包结构。
总结
本文到此结束,希望能对你有所帮助。欢迎继续关注本站获取更多精彩内容!
JS合并多个数组的三种方法:concat、spread与flat
2026-11-05 17:39:45
JavaScript怎么准确判断数据类型:typeof、instanceof与Object.prototype.toString
2026-11-05 17:09:21
JS中将数组和对象混合组装为JSON字符串
2026-11-05 16:41:42
JS运算符优先级与结合性的区别是什么?
2026-11-05 13:22:02
JS Map怎么只遍历Key或Value
2026-11-05 13:00:36
