我知道IIFE的典型形式是:
(function(){/* code */})()
然而,最近我发现了一个新的:
!function(){/* code */}()
+function(){/* code */}()
其也作为IIFE工作。
我认为在第一个!
中,值是布尔值,所以代码等价于true()
,在第二个+
中,值为数字,所以代码与NaN()
相同?但true()
和NaN()
不可能工作,而上述两种形式工作得很好。
这两种形式的IIFE是如何运作的?
function
关键字具有决斗目的。根据您在其中使用的上下文,它可以启动函数声明,也可以启动函数表达式。
函数声明在当前函数的作用域中声明一个(已提升的(局部变量,并将该函数分配给该变量。
函数表达式不需要,它们要求您立即对函数执行操作。常见的例子包括将其分配给对象的属性,将其作为参数传递给函数(即使其成为回调函数(或将其用作IIFE。
如果您尝试使用()
遵循函数声明,则它将出错。
function myFunction() {
console.log("Example");
}();
只有函数表达式才能立即调用函数表达式。(箭头函数也可以,但IIFE比它们老得多(。
因此,要使用IIFE,您必须执行操作来更改function
关键字出现的上下文,以便它用于创建表达式而不是声明。
经典的方法是将函数封装在括号中。
(function myFunction() {
console.log("Example");
})();
但是任何使其成为表达式的都会起作用。
将运算符(如!
或+
(放在function
关键字前面可以做到这一点。
而!
将取调用IIFE的返回值并将其转换为否定布尔值,+
将其转换成不是点的数字。运算符的左手边没有任何内容,因此值将被丢弃。
这只是使function
关键字创建一个可以转换为IIFE的函数表达式的一种方法。
请注意,IIFE的主要优势也由块范围的变量(let
和const
(和JavaScript模块提供,因此在2022年根本没有太多理由使用IIFE。
在!function() {}()
和+function() {}()
的情况下,JavaScript将首先计算给定语句/IIFE的右手边,然后在!
的情况下将IIFE的返回值强制转换为布尔值,在+
的情况下强制转换为类型号。如果IIFE返回布尔值,则!
将否定返回值。
示例
console.log(
!function() {
return "something";
}()
);
/**
!function() {
return "something";
}()
evaluates to
!"something" and not true() or false()
lastly !"something" is equivalent to false
*/
有很多方法可以让函数在定义后立即执行。常见的是,您必须确保函数不是被解释为函数语句,而是被解释为一个函数表达式。
通过在函数关键字前面加一个一元运算符,如!
或+
,或任何其他一元运算符(~
、-
、void
等(,可以避免function
被解释为语句。
任务也会起作用:
var x = function(){/* code */}()
或数组文字:
[function(){/* code */}()]
或者将其作为参数传递给(廉价的(函数:
Object(function(){/* code */}())
或者应用二进制运算符,前提是函数表达式是第二个操作数而不是第一个操作数。此处使用逗号运算符:
0,function(){/* code */}()