介绍
IIFE(Immediately Invoked Function Expression)中文名称:立即执行函数表达式
,是一种JavaScript编程模式,它允许函数在定义后立即执行。由这个定义可以看出IIFE有两个特点:
- 它是函数表达式
- 它是定义后立即执行的
来看一个例子:
1 | (function() { |
将这段代码放在浏览器控制台中执行,会输出I am an IIFE
。这就是一个简单的IIFE。
分析一下上面的代码,它分为两部分,每个部分由一组()
包裹。
第一部分是一个函数(本例用的是匿名函数,也可以是具名函数):
1 | (function() { |
第二部分是一个函数调用
1 | (); |
这两部分结合在一起,就形成了一个IIFE。
快速掌握IIFE
IIFE的语法其实不复杂,但是刚开始要记住它并不容易,这里教大家一个小技巧,可以快速书写IIFE代码。
- 首先,写下两组括弧
()()
- 然后在第一组括弧内写下函数定义 - 注意这里必须是匿名函数。
- 如果函数需要参数,那么在第二组括弧内传入参数。
一道练习题,写一个IIFE,计算1 + 2的和
我们使用上面的技巧来书写:
首先写下两组括弧
1 | ()() |
然后在第一组括弧内写下函数定义
1 | (function add(a, b) { |
因为这里的add函数需要参数,所以我们要在第二组括弧内传入参数
1 | (function add(a, b) { |
IIFE的变种
上面介绍的IIFE写法是最常见的形式,其实IIFE还有一些其他写法(至于为什么这些写法是可以的,我们下一篇再做介绍),现罗列如下:
这种写法将调用函数的括号放到了第一组括弧内部。
1 | (function() { |
以下几种写法都是使用一元运算符来实现的。
1 | !function() { |
这些一元运算符的作用是将函数定义转换为一个表达式,从而使其可以被调用。如果不加这些一元运算符的话,就变成了下面的形式:
1 | function() { |
这会导致一个语法错误,因为JavaScript引擎会将其解析为一个函数声明,而不是函数表达式。函数声明需要一个函数名,而匿名函数没有名字,所以会报错:
1 | Uncaught SyntaxError: Function statements require a function name |
我们给它加上一个名字,变成下面这样
1 | function foo() { |
但是还是会报错:
1 | Uncaught SyntaxError: Unexpected token ')' |
javascript引擎会将上述代码解析为一个函数声明和一个分组操作符 - 即()
,但是分组操作符内不能是空的,必须有一个表达式,我们在里面加上一个1
1 | function foo() { |
这样就不会报错了,但是这不是一个IIFE了。它的返回值就是分组表达式的值,也就是1。
为什么需要IIFE?
早期在JavaScript尚未支持模块化的时候,IIFE是实现模块化的一种简单方式,它可以创建一个独立的作用域,从而避免全局污染,下面看一个例子:
1 | const myModule = (function MyModule() { |
分析一下上面的代码,这是一个典型的IIFE + 闭包实现模块化的例子。
MyModule是一个IIFE,它在内部定义了:
- 私有变量
privateVariable
- 私有方法
privateMethod
这些变量和方法无法从外部访问。
它还定义了
- 一个公共变量
publicVariable
- 一个公共方法
publicMethod
这些可以通过返回的对象访问。
IIFE的返回值赋值给了myModule
变量,这样就可以通过myModule
访问公共变量和方法。
注意:这个例子仅供参考,在ES6模块已经十分普及的今天,这种方式已经不推荐使用了。