JS常见面试题之 详解js闭包,GitHub标星8k

百度百科定义:闭包就是能够读取其他函数内部变量的函数。

创建闭包的通常方式,是在一个函数内部创建另一个函数

在解释之前,得先讲讲作用域。先来看下面这个示例:

示例中包含了两种作用域,一种是属于全局的全局作用域,另一种是属于函数f的局部作用域。由于Javascript这种链式作用域(父作用域是可以被其子作用域访问的,而子作用域却不能被父作用域访问)的机制,使得示例最后一行输出了undefined

从此可以看出,无法从父作用域中访问子作用域。而我们再来看闭包的定义:闭包就是能够读取其他函数内部变量的函数。也就是闭包可以让我们从父作用域中访问到子作用域,具体怎么实现的呢?来看这个经典的例子

这个示例中,闭包就是函数bar。可以看到,我们通过在函数foo内部定义其子函数bar,并将其作为foo返回值,因为bar函数作用域可以访问foo的作用域,所以实现了从全局作用域访问foo函数作用域的效果。

有了前面知识的充分准备

我们正式进入讲解闭包

想要真正理解闭包,需要理解 执行环境和活动对象

执行环境和活动对象:

执行环境(execution context)定义了变量或者函数有权访问的其他数据,每个执行环境都有一个与之关联的变量对象(variable object),执行环境中定义的变量和函数就保存在这个变量对象中;

全局执行环境是最外围的一个执行环境,通常被认为是window对象

执行环境和变量对象在运行函数时生成

执行环境中的所有代码执行完以后,执行环境被销毁,保存在其中的变量和函数也随之销毁;(全局执行环境到应用退出时销毁)

一事无成的苦逼

我猜,看到这里,是不是觉得以上的理论很枯燥而且艰涩?因为基本上是从书上引用来的,不着急着理解,先摆在上面,等会结合案例回头再来看!相信你会恍然大悟,接下来请看样例:

在执行函数A的时候,创建了A的执行环境和变量对象,其中A的变量对象和全局变量对象中都含有a变量,根据作用域链从前向后查找,在A的变量对象中找到,所以输出1,执行完毕以后 ,A的执行环境销毁,A的变量对象由于没有被引用,所以也销毁;

上文我们提到了,由于作用域链的结构,外围函数是无法访问内部变量的,为了能够访问内部变量,我们就可以使用闭包,**闭包的本质还是函数。**也许你应该默认三遍 这句话 **闭包的本质还是函数

**,因为它实在是太重要了

上面就是一个很简单的闭包例子,通过m函数,我们可以获得A函数内部变量的值,这个样例比较简单,看不出什么问题,接下来我们来深入了解一下。

每次执行A函数时,都会生成一个A的活动变量和执行环境,执行完毕以后,A的执行环境销毁,但是活动对象由于被闭包函数引用,所以仍然保留,所以,最终剩下两个A的变量对象,因此m1和m2在操作x时,指向的是不同的数据,

现在来回答三个问题:

1.(为什么连续执行m1的时候,x的值在递增?)

answer:因为m1在引用的活动对象A一直没有释放(想释放的话可以让m1=null),所以x的值一直递增。

2.定义函数m2的时候,为什么x的值重新从1开始了?

answer:因为又一次运行了A函数,生成一个新的A的活动对象,所以m2的作用域链引用的是一个新的x值。

3.m1和m2里面的x为什么是相互独立,各自维持的?

answer:因为在定义m1和m2的时候,分别运行了A函数,生成了两个活动对象,所以,m1和m2的作用域链是指向不同的A的活动对象的。

好的,到这里先回顾一下前面说到的知识点:

执行环境和变量对象在运行函数时生成

执行环境中的所有代码执行完以后,执行环境被销毁,保存在其中的变量和函数也随之销毁;(全局执行环境到应用退出时销毁)

js高级设计

感觉理解了吗?接下来,再看看另一个很类似的例子:

这个例子和刚刚十分类似,不同的是,在A内部就先定义了两个函数,可以看出 ,最后的结果与上面的例子有些不同:

变量x仍然能保持递增,但是m[0]和m[1]定义的函数,对于x的改变不再是相互独立的,其实大家估计猜到了,这里的m[0]和m[1]的作用域指向的A的变量对象,其实是同一个,为什么呢?很简单,看看刚刚这段代码,其实是只调用了一次A函数,再看上文那句话:

执行环境和变量对象在运行函数时生成

既然A只执行一次,那么A的活动变量当然也就生成了一个,所以这里m[0]和m[1]的作用域指向同一个A的变量对象

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注:前端)
img

片转存中…(img-EkEvJbkX-1710883495477)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注:前端)
[外链图片转存中…(img-6i7gwAzt-1710883495477)]

  • 14
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值