日期:2024年10月15日

闭包(closure)

函数的外层作用域由函数定义的位置来决定,现在有如下代码:

function outer() {
     let a = 0;
     function inner() {
         console.log(a);
     }
     inner();
}
let a = 30;
outer();

现有全局函数outer,outer中有内部函数inner,在inner中访问了变量a,在outer中调用函数inner,在全局作用域中调用了函数outer。

现在思考,inner中打印的a的值是多少?

函数的外部作用域由其定义的位置决定,inner是outer的内部函数,inner的外层作用域是outer函数的作用域,所以此时在inner中打印的a的值是outer中a的值,也就是0。

现在修改代码,将inner函数作为函数的返回值返回

函数的外层作用域由函数定义的位置来决定,现在有如下代码:

function outer() {
     let a = 0;
     return function() {
         console.log(a);
     };
}
let a = 30;
let inner = outer();
inner();

上例中,我们将内部函数作为返回值返回。在全局作用域中使用变量inner来接收,然后调用了inner函数。此时函数虽然被一个全局变量引用,但是函数依然还是内部函数。我们在全局中调用了inner函数,此时inner中打印的a是多少?

还是要强调,函数的外层作用域由函数定义的位置决定的。所以上例中的inner函数,无论你在哪里调用,它的外部作用域都是outer函数的作用域,所以这里打印的a的值依然是0。

这就意味着即使outer函数已经调用完毕(outer函数在inner前被调用),其作用域的生命周期已经结束。但是它的内部函数inner依然可以访问到它的局部变量a。看到这我建议你先不要往下看,把上边的两个示例写一写,体会一下。

上边我们看到的这个,可以访问到外部函数作用域中变量的内部函数就被称为一个闭包。

闭包指内部函数总是可以访问到其外部函数作用域中的变量或参数。

上例中的inner函数,总是可以访问到外部函数中的变量a,并且此时外部函数的生命周期已经结束,这意味着变量a能且只能被inner访问到,这就形成了一个闭包,这个作用域只对inner开发放,对其他的对象封闭。

创建一个闭包,需要具备以下几个条件:
1.必须要有函数的嵌套
2.内部函数要引用外部函数中的变量
3.将内部函数作为返回值返回

闭包有什么用

仔细看起来闭包其实并没有什么神奇的,真的没有什么神奇的地方。它就是这么一个东西,但是这个东西却给很多的前端工程师带来了困扰,什么是闭包?不懂啊,带来这个问题的原因我觉得可能是它的倒霉名字,闭包这个名字确实很奇怪。

至于闭包有什么用,这个问题就比较难回答了,因为闭包在JS中几乎无处不在,太多的地方都可以使用闭包。但使用闭包的地方都有一个共同的特点就是“见不得人”,见不得人是一个比喻。闭包的核心就是创建了一个封闭的作用域,这个作用域只能被某个或某几个函数访问,这就使得我们可以在这个封闭的作用域中隐藏一些不希望被别人看见的东西(这就是所谓的见不得人),当然咱们也藏不了啥,顶多藏个变量参数啥的。

所以什么时候用闭包,当你需要藏起一些东西的时候,闭包是一个不错的选择。至于要藏什么就要看你个人的喜好了。现在你至少应该做到的是能识别出一个闭包。怎么识别,看看上边的三点。

5 1 投票
文章评分
订阅评论
提醒
guest

3 评论
最旧
最新 最多投票
内联反馈
查看所有评论
two
two
1 年 前

超哥,我想问一下我这样理解对不对。闭包就是一个作用域,该作用域在定义并且满足三个条件时才会产生,并且该作用域与函数条用无关(属于函数作用域的外层作用域?),该作用域只会存储被内部函数引用的外部函数的变量

two
two
1 年 前
回复给  李立超

好的,懂了谢谢超哥

3
0
希望看到您的想法,请您发表评论x