🧙‍♂️闭包应用场景之--IIFE

82 阅读2分钟

前言

前面写过关于JavaScriptthis指向的基础文章,链接:juejin.cn/post/751796…

今天我们继续来讲讲闭包的应用场景之一:IIFE

IIFE-立即执行函数

在讲实例前,先来回顾一下IIFE

const Counter = (function (){
    // 这里的代码会在定义时立即执行一次
    // ...
})();

(function(){ ... })() 是一个 IIFE(Immediately Invoked Function Expression),意思是“定义后立即执行”。

不管调不调用Counter,IIFE在它被定义完成时就会执行一次。

举个简单例子来理解:

const foo = (function() {
    console.log("IIFE 被执行了");
    return function() {
        console.log("我是返回的函数");
    };
})();

// 输出:IIFE 被执行了
// 此时还没有调用 foo()

"IIFE 被执行了" 已经输出了 —— 因为 IIFE 在定义的时候就执行了!

实例

const Counter = (function (){
    let count = 0; // 自由变量 私有
    function increment (){
        return ++count; // 闭包
    }
    function reset() {
        count = 0; // 闭包
    }

    return function(){
        return {
            getCount: function(){ // 闭包
                return count; // 闭包
            },
            increment: function(){
                return increment(); // 闭包
            },
            reset: function(){
                return reset(); // 闭包
            }
        }
    }
})();
const counter1 = Counter(); 
const counter2 = Counter(); 

console.log(counter1.getCount()); // 0
counter1.increment();
console.log(counter2.getCount()); // 1

这段代码的执行顺序如下:

第一步:定义并立即执行一个匿名函数
  • (function (){ ... })() 是一个 IIFE。
  • 这个函数在定义后立即执行,返回值赋给了 Counter
  • 所以此时 Counter 并不是函数本身,而是这个 IIFE 返回的结果 —— 也就是它内部的一个函数
第二步:IIFE 内部做了什么?
  1. 定义了一个局部变量 count = 0,这是私有变量,外部无法直接访问。

  2. 定义了两个函数:

    • increment():递增 count
    • reset():将 count 重置为 0
  3. 然后返回一个新的函数,这个函数每次被调用时会返回一个对象,对象中包含三个方法:

    • getCount():获取当前 count
    • increment():调用内部的 increment
    • reset():调用内部的 reset
为什么这些函数能访问到 count

因为它们都形成了 闭包,可以访问其外层作用域中的变量 count

 为什么会输出 0 → 1?

虽然看起来 counter1counter2 是独立的,但实际上:

return function(){
    return {
        getCount: function(){ return count; },
        increment: function(){ return increment(); },
        reset: function(){ return reset(); }
    }
}

这里的 count, increment, reset 都是在 IIFE 内部定义的,也就是说,所有的 Counter() 实例其实共享同一个 count 变量

所以实际上:

  • counter1.increment() 修改的是同一个 count
  • counter2.getCount() 获取的也是同一个 count

结尾

IIFE内部定义的变量都是私有的,我们可以通过闭包来访问,这就是闭包的应用场景之一--IIFE。