闭包真正的意义

541 阅读4分钟

前言

很多小伙伴在面试的时候都会被问到,闭包是什么?举例说明下闭包的运用场景?

八股文谁不会背呀,上网一搜,临时抱下佛脚便是。嘿嘿,我当时就是这么干的。

但是想要在面试中脱颖而出,死记硬背理论是远远不够的,面试官如果问的再深入一些,就要凉凉。

关于闭包的讨论和文章有很多,但我个人认为,许多都没有讲到核心点上。所以自己总结一番,加深自己理解的同时,也希望能帮助到各位看官。

闭包,究竟是什么

闭包就是能够读取其它函数内部变量的函数

但凡背过面试题的朋友,对这句话就一定不会陌生。网上对于闭包的解释,十之八九离不开这句话,大差不差。

以这句话来解释闭包,没错,但没有灵魂,像一个复读机。

我们首先要知道,闭包存在的意义是什么?可以简单概括为,实现从外部读取函数内部的局部变量。

我们有时候需要获取到函数内部的局部变量,正常情况下,这是办不到的。只有通过变通的方式才能实现,比如在函数内部,再定义一个函数。举个栗子:

function f1() {
    var a = 1;
    function f2() {
        alert(a);
    } 
    f2();
}
f1(); // 可以获取到局部变量 a

请回答我,上栗是不是闭包?

是不是在 f1 函数内部定义了一个 f2 函数?

是不是 f2 函数读取到了 f1 函数内部的局部变量?

那么,这到底是不是闭包呢?

如果你迟疑了,我们再看个栗子。获取函数内部的局部变量,其实并不需要那么费劲,还有一种更简单的方法:

function f() {
    var a = 1;
    return a;
}
f(); 

这是闭包吗?大家都知道,很显然,它不是。第一个栗子也不是。

那么,到底怎样才算是闭包呢?我们来看一下真正的闭包:

function f1() {
    // 定义一个局部变量
    var a = 1; 
    // 定义一个函数,引用了局部变量 a
    function f2() {
        a++;
        console.log(a);
    } 
    // 将内部函数 f2,return 出去
    return f2; 
}

// 调用 f1,返回的是 f2 函数,赋值给 f
var f = f1();
// 调用 f,打印 a 的值为 2
f();

同样是访问函数内部的局部变量,为什么需要写的这么麻烦呢?为什么之前那样变通的写法就不算是闭包呢?继续看栗子:

// 闭包
function f1() {
    var a = 1; 
    function f2() {
        a++;
        console.log(a);
    } 
    return f2; 
}

var f = f1();
f(); // 2
f(); // 3
f(); // 4

不断调用 f,变量 a 的值会一直累加。由于函数 f 引用着变量 a 的值,导致变量 a 不会被垃圾回收机制自动回收,所以它的值会一直保存在内存中。

// 非闭包
function f1() {
    var a = 1;
    function f2() {
        a++;
        console.log(a);
    } 
    f2();
}
f1(); // 2
f1(); // 2
f1(); // 2

每次调用,变量 a 的值都是 2。每次调用,函数以及内部变量都会重新创建,执行完毕之后就会销毁。

有的朋友可能会想到,把变量 a 定义到全局不也能实现长久保存吗:

var a = 1;
function f() {
    a++;
    console.log(a);
}
f(); // 2
f(); // 3
f(); // 4

是的,可以实现。但是全局变量很容易造成污染,在实际项目开发中,我们不可能定义那么多的全局变量。

总结一波:

闭包的作用:闭包最大的用处有两个,一个是前面提到的可以读取函数内部的局部变量,另一个就是让这些变量的值始终保存在内存中。

什么时候使用闭包:局部变量无法共享和长久保存,而全局变量可能造成污染,当我们希望有一种机制既可以共享、长久保存变量,还不会造成污染时,就需要运用闭包。

闭包的定义:闭包是一种现象,当一个函数返回的是一个函数,并且被返回的这个函数对于局部变量存在引用,就形成闭包。

闭包的弊端:由于闭包会导致变量长驻在内存中,过度使用闭包可能会造成内存泄漏。

闭包具体的使用场景

比较经典的有:

  • 模块化
  • 函数节流
  • 函数防抖
  • 函数柯里化 关于闭包的具体使用场景有很多,以上仅供参考,想再深入的朋友可以看看其它文章,我就不一一展开讲了~

最后

如果文中有错误或者不足之处,欢迎大家在评论区指正。

你的点赞是对我莫大的鼓励!感谢阅读~