JS立即执行函数:(function(){})( ) 与 (function(){}( )) 的区别解析
本文解析JavaScript中立即执行函数(IIFE)的两种常见写法:(function(){})( ) 与 (function(){}( ))。通过对比函数声明与表达式的区别,说明括号包裹将声明转为表达式从而触发执行的核心原理。文章指出这两种写法在功能上完全等价,均用于创建独立作用域以避免污染全局命名空间,并列举了void、!等其它转换方式。
IIFE两种写法对比
这两种写法没有区别。
要理解这一点,需要掌握立即执行函数表达式(IIFE)的基本原理,下面简要说明。
参考以下代码示例:
function foo() {...} // 这是函数声明(Declaration);声明仅告知解释器该函数的存在,并不会立即执行。
foo(); // 这是函数调用语句(Statement);解释器遇到语句时会执行它。
IIFE 并非必须使用的模式,采用传统方式也可以实现相同效果:
参考以下代码示例:
function foo() {...}
foo();
IIFE的使用动机
那么为什么要使用 IIFE? 1.传统方法较为繁琐,函数定义和执行需要分开书写; 2.传统方法会直接污染全局命名空间(在浏览器环境中指 global 对象,如 window)。
因此,开发者寻求一种能解决上述问题的写法。那么尝试下面这种写法是否可行?
function foo(...){}();
答案是不行。原因在于 function foo(...){} 这部分仅是一个声明,对于解释器而言,它类似于一个字符串 "function foo(...){}",必须通过解析函数(如 eval())才能执行。因此,直接在声明后放置 () 不会触发执行,这属于错误语法。
从声明到表达式的转换
如何修正使其正确?方法很简单,只需将 声明 转换为 表达式(Expression) 即可。
实际上,转换表达式的方法有多种,最常见的方式是用一对括号将函数声明包裹起来,从而变为:
参考以下代码示例:
(function foo() {...}) // 此处故意换行,实际书写时可与下方括号连写
();
这等同于:
参考以下代码示例:
var foo = function () {...}; // 这不再是声明,而是表达式。
foo();
之前提到的不可行写法,其实也可以直接用括号包裹,这也是一种等价的表达式形式:
(function foo(){...}());
因此,你问有没有区别?答案很简单:没有。
其他表达式转换方式
另外,前面提到转换表达式的方式很多,确实还有其他写法,例如:
!function foo() {...}();
或者
+function foo() {...}();
这些写法都是有效的。
我个人更倾向于使用 void 关键字来转换表达式,因为该关键字不会产生返回值。当然,这一点并不重要,可以视为个人偏好。
参考以下代码示例:
void function () {
// 这里是真正需要的代码
}();
作用域与全局对象处理
OK,所谓不污染全局命名空间,是因为 IIFE 创建了一个新的函数作用域,真正的业务代码被封装在其中,自然就不会触碰到全局对象。如果需要访问全局对象,可以将其作为参数传递给 IIFE:
参考以下代码示例:
void function (global) {
// 在这里,global 就是全局对象了
}(this) // 在浏览器环境中,this 指向 window 对象
我曾撰写过相关系列文章,其中一篇讲解作用域和命名提升,其中的知识点有助于理解 IIFE,有兴趣可深入阅读:https://www.jb51.net/article/75090.htm
方式一,调用函数,得到返回值。强制函数直接量执行再返回一个引用,引用再去调用执行。 方式二,调用函数,得到返回值。强制运算符使函数调用执行。 (function(){})(); 是将函数当作表达式解析,然后执行解析后的函数。 相当于 var a = function(){}; a(); a得到的是函数。 (function(){}()); 是将函数表达式和执行当作语句直接执行。 相当于 var a = function(){}(); a得到的是结果。 最终结果是一样的。 ()只是起了自执行的作用。 和 () 一样的还有很多。 比如 +function (){} 这个等于 (function (){}) 一般用(function (){}) 还有个作用,就是 避免全局变量
什么时候该用JS构造器:与工厂模式、字面量的选择对比
2026-11-05 16:18:22
推荐几款轻量级JS照片墙开源库及对比
2026-11-05 15:56:19
JavaScript递归写法有哪些常见陷阱及避免方法
2026-11-05 14:53:38
JS数组浅拷贝与深拷贝怎么选?场景与方法总结
2026-11-05 14:41:02
p5.js 中 setup() 和 draw() 函数的执行机制详解
2026-11-05 12:32:38
