javascript之温习闭包

闭包的定义:闭包是由函数和函数能够访问的自由变量所组成,即使创建它的上下文已经被销毁,它依然存在。

  1. 最经典的例子:
for (var i = 0; i < 10; i ++) {
    setTimeout(function () {
        console.log(i)
    }, i * 1000)
}
复制代码
  • 毫无疑问,我们都知道这里将会每隔1s输出一个10,为什么呢?我们可以利用Event Loop来解释这一现象。当程序开始执行的时候,同步和异步任务分别进入不同的执行"场所",同步的进入主线程,异步的进入Event Table并注册函数。在这里,for会进入主程序开始执行,而setTimeout进入Event Table ,并注册回调函数。由于js引擎存在monitoring process进程,会持续不断的检查主线程执行栈是否为空,一旦为空,就会去Event Queue那里检查是否有等待被调用的函数。而此时,for循环已经执行完毕,此时的i成为全局变量,Event Queue中的函数访问到的变量i均为10
解决方法有很多,比如使用IIFE,或者ES6中的let来创建块级作用域。这里列出一个通过js值类型的方法来决定这个问题:
function func (i) {
    setTimeout(function() {
        console.log(i)
    }, i * 1000)
}
for (var i = 0; i < 10; i ++) {
    func(i)
}
复制代码
最后,我们来分析一下下面这道面试必刷题
var arr = []
for (var i = 0 ; i < 5; i ++) {
    arr[i] = (function(j) {
        return function() {
            console.log(j)
        }
    })(i)
}
arr[0]() // 0
arr[1]() // 1
arr[2]() // 2
...
复制代码
  • 这里我们是通过IIFE来实现往数组中添加值的,数组的每一项值都是一个函数,调用函数,打印出循环变量 i
  • 当执行到 arr[0]() 时,函数 arr[0]的作用域链表示如下 :
    // AO 表示活动对象, VO表示变量对象,其实它俩是等价的
    函数上下文 [AO, anonymous(匿名函数)context.VO,Global(全局)context.VO]
复制代码
  • 执行函数arr[0]()的时候,首先函数会到自己的AO中寻找是否存在变量 i,没有找到就会去匿名函数中的VO寻找变量 i (i = 0),此时,通过闭包,我们将每次循环的变量i 都存在其上下文中,能够访问到,便输出 i,并不再向GlobalContext中的VO( i 的值为 5)寻找了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值