某世界第一大运动,我们称呼它为“足球”,而英国人称呼它“football”,但其本质概念就是“用脚踢的一种球”。只不过每个国家对它的称呼不同而已。同样道理,闭包也是一种概念/机制(用脚踢的一种球),很多编程语言都可以实现闭包。

1、之所以会有闭包这个概念,是因为编程语言的一些特性,来看下面的代码表达的信息:

  • 在函数 outer 内部,可以访问到变量 a
1
2
3
4
5
    let a = 0;
    function outer() {
        alert(a);
    }
    outer();

2、那如果我把 let a = 0 放到 outer 函数内部并且把 alert(a)放到 outer 函数外部,会发生什么呢?

  • 浏览器会报 Uncaught ReferenceError: a is not defined 的错误
  • 这里之所以会报错,就是因为 JS 的特性:在函数外部正常情况下没有办法读取到函数内部的值
1
2
3
4
    function outer() {
        let a = 0;
    }
    alert(a);

3、那么问题来了,如果我一定想在 outer 函数外部访问到 a,该怎么办呢?先上代码:

  • 下面的代码在 outer 内部定义了一个函数 inner,在 inner 内部 alert 了 a,然后把 inner 返回了
  • 这个时候我们在外部先做一个函数引用,把 outer 函数赋值给 r,然后我们直接调用 r
  • 这个时候浏览器就会 alert 出 a 的值
1
2
3
4
5
6
7
8
9
    function outer() {
        let a = 1;
        function inner() {
          alert(a);
        }
        return inner;
    }
    let r = outer();
    r();

4、如果上面的三段代码你都能看懂,那么我现在告诉你第三段代码中的 inner 函数就是“闭包”,当然这里是用代码解释的。如果用文字解释的话,我的理解就是闭包就是可以读取其他函数内部变量的函数,上面的 inner 函数可以读取 outer 函数内部的变量 a,所以 inner 函数就是闭包。

5、总结:闭包就是让我们可以在外部访问到函数内部的变量,这样我们就可以在外部操作函数内部的变量,这样就可以实现一些特殊的功能。

6、顺便扔一个思考题,下面的代码为什么不能 alert 出 a 的值?

1
2
3
4
5
6
7
8
    function outer() {
        let a = 1;
        function inner() {
          alert(a);
        }
        return inner;
    }
    outer()