深入理解IIFE

1,304 阅读2分钟

什么是IIFE ?

IIFE 立即调用函数表达式(英文:immediately-invoked function expression,缩写:IIFE)

立即调用函数表达式拥有数种不同的写法。最常见的一种是将函数表达式字面量至于圆括号(分组运算符)之内,然后使用圆括号调用函数

(function() {
  // 这里将获得新的作用域
})();

若要将作用域外变量传递进函数,则按下述方式书写

(function(a, b) {
  // a == 'hello'
  // b == 'world'
})('hello', 'world');

iife 可以用来解决新的变量被解释成全局变量或函数名占用全局变量名的情况

例如

for (var i = 0; i < 5; i++) {
   setTimeout(function(){
       console.log(i)
   }, 0)
}
console.log(i)

上面代码输出6个5因为循环输出5个最后console.log()输出一个,因为根据作用域的工作原理,实际情况是尽管循环中的五个函数是在各个迭代中分别定义的,但是它们都被封闭在一个共享的全局作用域中,因此实际上一有一个i。 如果我们在循环中创建iife 创建新的作用域并获取i就能得到我们想要的结果

for (var i = 0; i < 5; i++) {
    (function(j){
        setTimeout(function(){
            console.log(j)
        }, 0)
    })(i)
   
}
console.log(i)
//  5 0 1 2 3 4

用let声明也可以解决这个问题,本质上是将一个块转换成一个可以被关闭的作用域

for (var i = 0; i < 5; i++) {
    let j = i;
    setTimeout(function () {
        console.log(j)
    }, 0)


}
console.log(i)

如果在for 循环中使用let i = 0 还会有一个特殊的行为,这个行为是在循环过程中不止被声明一次,每次迭代都会声明,随后每个迭代都会使用上一个迭代结束的值来初始化这个变量

for (let i = 0; i < 5; i++) {
    setTimeout(function () {
        console.log(j)
    }, 0)
}
console.log(i)

IIFE中定义的任何变量和函数,都会在执行结束时被销毁,这种做法可以减少闭包占用的内存问题,因为没有指向匿名函数的引用。只要函数执行完毕,就可以立即销毁其作用域链了。