资讯专栏INFORMATION COLUMN

闭包

FWHeart / 1680人阅读

摘要:在中,闭包其实随处可见。但真要说起什么是闭包的话,很多人可能一时半会不知道怎么解释。这篇博文主要写一些闭包的特性已经相关的应用。

在JavaScript中,闭包其实随处可见。但真要说起什么是闭包的话,很多人可能一时半会不知道怎么解释。这篇博文主要写一些闭包的特性已经相关的应用。
参考资料:阮一峰——JavaScript运行机制详解
定义

闭包是指在函数声明时的作用域以外的地方被调用的函数,在函数声明时的作用域以外的地方调用函数,需要通过将该函数作为返回值或者作为参数被传递

特性

光看定义的话可能会比较懵逼(╯‵□′)╯︵┻━┻ 下面来看一下闭包到底都有哪些特性:

函数在自己定义的词法作用域以外的地方执行

函数嵌套

访问所在的词法作用域

循环闭包 定义

在循环中包含了函数定义则称为循环闭包

实例1

讲了这么多,下面来看一段例子:

for(var i = 1; i < 6; i++){
    setTimeout(function(){
        console.log(i);
    },50);
}
//输出结果为: 6 6 6 6 6

好吧,如果你是新手的话,看到这里你是震惊的,因为作为一个萌新,当初我对这串代码的想法是这样的:

setTimeout函数在for循环中执行六次,每隔50ms输出一个数字,则会分别输出1、2、3、4、5

后来我发现,用关键字var声明的变量会存在变量提升的情况,循环结束以后,变量i不会被JavaScript引擎的垃圾回收机制回收,而是成为全局变量。
所以我的的初步解释为:

由关键字var声明的变量存在变量提升的情况,循环结束以后变量i变为全局变量

for循环结束的比50ms要早,所以setTimeout函数读取不到迭代的变量i,而是循环结束后的变量i

实例2

然而上面只是我一开始错误的认识,直到我看到下面的代码:

for(var i=1;i<6;i++){
    setTimeout(function(){
        console.log(i);
    },0);
}
//输出结果为: 6 6 6 6 6

因为这里setTimeout的时间参数是0,如果照着上面的思路来的话,这里的输出应该是 1 2 3 4 5

JavaScript调用机制

在讲述解决方法之前我们先来了解一下JavaScript的调用机制

对JavaScript比较熟悉的人应该了解,JavaScript是一种单线程的语言。而我们在编写代码的时候,往往不止同步的代码,还有异步执行的代码,JavaScript这里把它分成两种模式,一种叫做同步任务,另一种则叫做异步任务。在执行代码的时候,同步任务被分配在主线程中执行,形成一个调用栈;而异步任务则交给浏览器的其他线程去执行。当异步任务执行完毕以后,则将对应的异步任务放入任务队列中。当调用栈中的任务都执行完毕以后,再读取任务队列,取消对应任务的等待状态,然后进入调用栈,开始执行。
解决方法

方法1:绑定作用域,将关键字var改为let,具体代码为:

for(let i=1;i<6;i++){
   setTimeout(function(){
       console.log(i)
   },50)
}

方法2:运用IIFE(立即执行函数),具体代码为:

for(var i=1;i<6;i++){
   (function(j){
       setTimeout(function(){
           console.log(j)
       },50)
   })(i);
}

在迭代内部使用IIFE会为每个迭代生成一个新的作用域,使得延迟函数的回调可以将新的作用域封闭在每个迭代内部,每个迭代都含有一个具有正确值的变量供我们访问

总结

闭包在JavaScript里随处可见,我们在使用闭包的时候,需要谨慎的在循环内部添加闭包。个人觉得最好的解决方案就是使用关键字let,可读性强而且另代码整洁,希望ES6能够全面普及。

扫描下方的二维码或搜索「tony老师的前端补习班」关注我的微信公众号,那么就可以第一时间收到我的最新文章。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/85016.html

相关文章

  • JS 中的闭包是什么?

    摘要:大名鼎鼎的闭包面试必问。闭包的作用是什么。看到闭包在哪了吗闭包到底是什么五年前,我也被这个问题困扰,于是去搜了并总结下来。关于闭包的谣言闭包会造成内存泄露错。闭包里面的变量明明就是我们需要的变量,凭什么说是内存泄露这个谣言是如何来的因为。 本文为饥人谷讲师方方原创文章,首发于 前端学习指南。 大名鼎鼎的闭包!面试必问。请用自己的话简述 什么是「闭包」。 「闭包」的作用是什么。 首先...

    Enlightenment 评论0 收藏0
  • 闭包,又见闭包。。。。?

    摘要:完美的闭包,对,闭包就这么简单。这仅仅是闭包的一部分,闭包利用函数作用域达到了访问外层变量的目的。此时一个完整的闭包实现了,的垃圾回收机制由于闭包的存在无法销毁变量。 1.闭包是指有权访问另一个函数作用域中的变量的函数。 上面这段话来自 javascript 高级程序设计 第三版 P178 。作者说闭包是一个函数,它有访问另一个函数作用域中的变量的能力。 2.函数访问它被创建时所处的...

    keelii 评论0 收藏0
  • 多层级理解闭包

    摘要:第二梯队理解有了第一梯队的认识,我们慢慢修正大脑中对闭包的认识。理解这句话就可以很好的与闭包这两个字关联起来理解闭包这个概念了。总结第二梯队理解闭包是一个有特定功能的函数。第四梯队理解闭包通过访问外部变量,一个闭包可以维持这些变量。 闭包 闭包的概念困惑了我很久,记得当时我面试的时候最后一面有一个问题就是问题关于闭包的问题,然而到现在已经完全不记得当时的题目是啥了,但仍然能够回忆起当时...

    nemo 评论0 收藏0
  • 面试官问我:什么是JavaScript闭包,我该如何回答

    摘要:到底什么是闭包这个问题在面试是时候经常都会被问,很多小白一听就懵逼了,不知道如何回答好。上面这么说闭包是一种特殊的对象。闭包的注意事项通常,函数的作用域及其所有变量都会在函数执行结束后被销毁。从而使用闭包模块化代码,减少全局变量的污染。 闭包,有人说它是一种设计理念,有人说所有的函数都是闭包。到底什么是闭包?这个问题在面试是时候经常都会被问,很多小白一听就懵逼了,不知道如何回答好。这个...

    BenCHou 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<