js闭包总结——含经典案例

闭包总结

闭包(Closure),官方点的定义是:内部函数可以对外部函数作用域里的变量进行引用,这个内部函数就是闭包。简单的说,闭包呢就是一个可以引用(读取)其他函数内部变量的一个函数。
闭包作为面试以及JavaScript当中的一个重难点,它可以在很多的场景当中灵活的使用,说说它主要的几个特点:

  • 可以使得在外部访问内部函数的变量;
  • 延长了内部函数生效的作用域链;
  • 可以减少全局变量的使用,避免全局变量污染;
  • 使得局部变量可以保存在内存当中使用,不被立即销毁(但是可能会造成内存泄漏,因为局部变量会使得一部分内存被长期占用得不到释放).

然后是闭包常见的几种存在方式:

1、嵌套函数的形式; 2、函数返回值的形式;
3、let形成块级作用域的形式(这种不算是严格的闭包形式,但是作用却是相同的,后面的案例会有介绍).

经典案例(详解)

根据闭包的这些特点,使得它有了了广泛地应用空间,下面就一个经典的案来深入的了解闭包。(直接上图)
在这里插入图片描述
这个案例要达到的效果是点击浏览器中的五个按钮可以在控制台打印对应的序号,首先我们看这段代码,这并不是一个闭包的形式,但是很多的初学者就容易在这里入坑。
运行这段代码执行结果是:点击任何一个按钮都只会输出6。为什么呢?因为内部的匿名函数需要通过点击事件触发执行,当浏览器运行的时候,for循环立马就会将循环执行完毕,当我们点击触发事件的时候,内部的函数就需要输出i+1,但是内部没有定义的变量i,所以它就会按照作用域链就近取得外部的全局变量i,然后我们结果就会都是6.

下面我们再来看下面的代码:
在这里插入图片描述
通过修改上面的代码我们就可以实现想要的效果,这里就使用了闭包。
在这里我们添加了一个立即执行函数(不需要调用自己就可以执行),将输出序号的函数以返回值的形式放置,也就是上面我们说的闭包的第二种存在形式,最后将参数i传递给立即执行函数。这样我们就得到了一个闭包,return返回的就是闭包函数。

当我们执行代码的时候,同样的首先执行for循环,但是这里就和之前的情况不同,每次循环的i(立即执行函数的实参)的值都会通过参数传递到立即执行函数成为内部的局部变量i(立即执行函数的形参)中,由于内部是闭包函数,所以传入的i会保存在内存当中,供闭包函数的使用。
当我们运行之后,点击按钮触发内部的闭包函数,由于闭包函数作用域当中并没有定义的变量i,所以它按作用域链向上搜索 i,找到立即执行函数中保存的局部变量 i 进行引用,最终实现我们想要的效果

最后,我们还有一种方法也可以实现这里的效果,就是上面说的第三种闭包的形式,这种方式是es6带给我们的好处。
直接上代码---------
在这里插入图片描述
通过观察我们就会发现这里是不是和第一张代码相同呢,其实我们这里就只是将for循环当中的var改成了es6当中的let来进行定义。(后面准备专门就定义变量这块也做一个总结,期待吧~)

问:为什么这里更改一个定义变量的方式就能实现效果呢?
答:因为let定义的变量是一个块级作用域,它可以使得for,while,if等这些也成为块级作用域,让外部无法访问。

了解了原因,我们就可以来分析上面代码究竟是怎么执行:
首先,通过let定义变量使得for循环当中也成为块级作用域,然后内部有一个需要通过事件来触发的函数,这样我们就形成了一个类似于闭包的形式。所以运行代码之后,每次循环得到的局部变量i值会同样的保存在内存当中不会销毁,然后当我们点击按钮触发之后执行内部的函数,同样由于内部的函数没有定义变量i,就会就近寻找到for循环这个块级作用域当中的局部变量i进行引用,最后同样得到了我们想要的结果

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值