IIFE 的另一种写法
在 JavaScript 中,IIFE 最常见的写法是:
(function () {
console.log('立即执行');
})();外面那层括号的作用在于让 JavaScript 引擎把 function 关键字解析成函数表达式,避免被当成函数声明。函数声明必须有名字,也不能直接跟调用括号;函数表达式则可以匿名,也可以立即调用。
括号并非唯一选择,任何一元运算符放在 function 关键字前面,都能达到同样效果,例如 !、+、-、~,甚至 void:
!function () {
console.log('! IIFE');
}();
+function () {
console.log('+ IIFE');
}();
-function () {
console.log('- IIFE');
}();
~function () {
console.log('~ IIFE');
}();
void function () {
console.log('void IIFE');
}();为什么一元运算符可以替代外层括号?
关键在于 JavaScript 的语法解析规则:当 function 出现在语句开头时,解析器倾向于把它当作函数声明
function () {
// SyntaxError: Function statements require a function name
}一元运算符只能接受表达式作为操作数。解析器看到 !function () {} 它必须把后面的 function () {} 当作一个表达式来处理,否则 ! 就没有合法操作数。于是,function 被强制进入表达式上下文,变成函数表达式。
返回值被改变了
虽然这些写法都能让函数立即执行,但整个表达式的结果并不一样。例如:
var a = !function () {
return 0;
}();
console.log(a); // true函数返回 0,!0 得到 true。再比如:
var b = +function () {
return '42';
}();
console.log(b); // 42+ 把字符串 '42' 转成了数字。void 则比较特殊:
var c = void function () {
return 'hello';
}();
console.log(c); // undefined所以,如果你不关心 IIFE 的返回值,这些写法通常没有问题
分号仍然很重要
使用一元运算符写法时,仍然要注意自动分号插入带来的风险。例如:
var a = 1
!function () {
console.log('x');
}()这段代码可能不会按预期解析,因为上一行没有分号,! 可能被当成与上一行相连的一部分。更稳妥的写法是主动加分号:
var a = 1;
!function () {
console.log('x');
}();同样,传统的括号写法如果以前一行没有分号,也可能出现类似问题:
var a = 1
(function () {
console.log('x');
})()因此,无论选择哪种风格,团队中统一分号习惯都很重要
应该使用哪种写法?
从语义清晰度看,标准括号写法最直观:
(function () {
// ...
})();它明确表达了「这是一个函数表达式,并且立即调用」。一元运算符写法更短,在压缩代码或某些老式代码库中很常见,尤其是 !function(){}()。但它也有代价:!、+、-、~ 会改变返回值,void 虽然能明确返回 undefined,但对不熟悉的人来说可能不够直观。
在现代 JavaScript 中,IIFE 的使用场景已经比过去少了很多:块级作用域、模块系统、箭头函数等特性分担了它的一部分职责。但如果确实需要 IIFE,建议根据团队规范选择一种统一风格:追求可读性就用括号;追求简短且不关心返回值,可以用 ! 或 void;无论哪种,都别忘了分号和对返回值的预期。
归根结底,!function(){}() 它和 (function(){})() 一样,都在告诉 JavaScript 解析器:这里是一个函数表达式,请立即调用它