js中的闭包[通俗易懂]

js中的闭包[通俗易懂]闭包是js的一个难点也是它的一个特色,是我们必须掌握的js高级特性,那么什么是闭包呢?它又有什么用呢?我们都知道,js的作用域分两种,全局和局部,基于我们所熟悉的作用域链相关知识,我们知道在js作用域环境中访问变量的权利是由内向外的,内部作用域可以获得当前作用域下的变量并且可以获得当前包含当前作用域的外层作用域下的变量,反之则不能,也就是说在外层作用域下无法获取内层作用域下的变量,同样在不同的函…

大家好,又见面了,我是你们的朋友全栈君。

闭包是js的一个难点也是它的一个特色,是我们必须掌握的js高级特性,那么什么是闭包呢?它又有什么用呢?

我们都知道,js的作用域分两种,全局和局部,基于我们所熟悉的作用域链相关知识,我们知道在js作用域环境中访问变量的权利是由内向外的,内部作用域可以获得当前作用域下的变量并且可以获得当前包含当前作用域的外层作用域下的变量,反之则不能,也就是说在外层作用域下无法获取内层作用域下的变量,同样在不同的函数作用域中也是不能相互访问彼此变量的,那么我们想在一个函数内部也有限权访问另一个函数内部的变量该怎么办呢?闭包就是用来解决这一需求的,闭包的本质就是在一个函数内部创建另一个函数。
我们首先知道闭包有3个特性:
①函数嵌套函数
②函数内部可以引用函数外部的参数和变量
③参数和变量不会被垃圾回收机制回收

本文我们以闭包两种的主要形式来学习
在这里插入图片描述

在这段代码中,a()中的返回值是一个匿名函数,这个函数在a()作用域内部,所以它可以获取a()作用域下变量name的值,将这个值作为返回值赋给全局作用域下的变量b,实现了在全局变量下获取到局部变量中的变量的值

再来看一个闭包的经典例子
在这里插入图片描述

一般情况下,在函数fn执行完后,就应该连同它里面的变量一同被销毁,但是在这个例子中,匿名函数作为fn的返回值被赋值给了fn1,这时候相当于fn1=function(){var n = 0 … },并且匿名函数内部引用着fn里的变量num,所以变量num无法被销毁,而变量n是每次被调用时新创建的,所以每次fn1执行完后它就把属于自己的变量连同自己一起销毁,于是乎最后就剩下孤零零的num,于是这里就产生了内存消耗的问题

再来看一个经典例子-定时器与闭包

写一个for循环,让它按顺序打印出当前循环次数
在这里插入图片描述

按照预期它应该依次输出1 2 3 4 5,而结果它输出了五次5,这是为什么呢?原来由于js是单线程的,所以在执行for循环的时候定时器setTimeout被安排到任务队列中排队等待执行,而在等待过程中for循环就已经在执行,等到setTimeout可以执行的时候,for循环已经结束,i的值也已经编程5,所以打印出来五个5,那么我们为了实现预期结果应该怎么改这段代码呢?(ps:如果把for循环里面的var变成let,也能实现预期结果)

在这里插入图片描述

引入闭包来保存变量i,将setTimeout放入立即执行函数中,将for循环中的循环值i作为参数传递,100毫秒后同时打印出1 2 3 4 5

那如果我们想实现每隔100毫秒分别依次输出数字,又该怎么改呢?

在这里插入图片描述

在这段代码中,相当于同时启动3个定时器,i*100是为4个定时器分别设置了不同的时间,同时启动,但是执行时间不同,每个定时器间隔都是100毫秒,实现了每隔100毫秒就执行一次打印的效果。

②闭包作为参数传递

在这里插入图片描述

在这段代码中,函数fn1作为参数传入立即执行函数中,在执行到fn2(30)的时候,30作为参数传入fn1中,这时候if(x>num)中的num取的并不是立即执行函数中的num,而是取创建函数的作用域中的num这里函数创建的作用域是全局作用域下,所以num取的是全局作用域中的值15,即30>15,打印30

最后总结一下闭包的好处与坏处
好处

①保护函数内的变量安全 ,实现封装,防止变量流入其他环境发生命名冲突

②在内存中维持一个变量,可以做缓存(但使用多了同时也是一项缺点,消耗内存)

③匿名自执行函数可以减少内存消耗

坏处

①其中一点上面已经有体现了,就是被引用的私有变量不能被销毁,增大了内存消耗,造成内存泄漏,解决方法是可以在使用完变量后手动为它赋值为null;

②其次由于闭包涉及跨域访问,所以会导致性能损失,我们可以通过把跨作用域变量存储在局部变量中,然后直接访问局部变量,来减轻对执行速度的影响

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/149083.html原文链接:https://javaforall.net

(0)
上一篇 2022年6月25日 下午8:00
下一篇 2022年6月25日 下午8:16


相关推荐

  • Java冒泡排序实现

    Java冒泡排序实现Java冒泡排序原理:依次比较相邻的两个书,将较大的数放右边思路:依次比较相邻的两个数,将小数放在前面,大数放在后面。即在第一趟:首先比较第1个和第2个数,将小数放前,大数放后。然后比较第2个数和第3个数,将小数放前,大数放后,如此继续,直至比较最后两个数,将小数放前,大数放后。重复第一趟步骤,直至全部排序完成。冒泡排序的优点:每进行一趟排序,就会少比较一次,因为每进行一趟排序都会找出一个较大值。代码演示:…

    2022年7月8日
    23
  • 简图记录-曾国藩家训 观后感「建议收藏」

    简图记录-曾国藩家训 观后感「建议收藏」简图记录 总结~材料 郦波教授的百家讲坛 和 部分相关书籍  一个人疑惑的时候,总是希望通求知如过阅读找到自己的答案,读史可以使人明智,历史总是有借鉴意义,相对于空谈鸡汤无疑更有说服力。我认为向周围的人学习是个人成长一个非常重要的手段,周围的人都是真实的而且在一定范围是可交流讨论的,相对一些当代的名人 他们的事迹往往都是经过加工 或 胡编 鸡汤意味更浓一些,那么另外一条路就是找一些古代的贤…

    2022年6月4日
    36
  • clion永久激活码2021(注册激活)

    (clion永久激活码2021)2021最新分享一个能用的的激活码出来,希望能帮到需要激活的朋友。目前这个是能用的,但是用的人多了之后也会失效,会不定时更新的,大家持续关注此网站~IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html…

    2022年3月26日
    1.2K
  • Coze(扣子)智能体工作流:自动批量生成小红书图文,1分钟100篇

    Coze(扣子)智能体工作流:自动批量生成小红书图文,1分钟100篇

    2026年3月12日
    3
  • 大数据可视化方法有哪些「建议收藏」

    大数据可视化方法有哪些「建议收藏」  随着计算机技术、物联网技术和现代智能终端技术的发展,大数据时代已经到来。大到企业、政府、媒体部门,小到个人,每天都在进行”读读”。各种各样的复杂数据和信息充斥着人们的眼球。这就需要一种有效的方法从海量信息中提取有用的信息,并能立即产生一定的相关结果,供决策者做出正确的决策。  数据可视化技术是指可视化技术在大数据方面的应用,将数据信息转化为视觉形式的过程,以此增强数据呈现的效果。用户…

    2022年6月3日
    39
  • numpy float转int_python字符串转float类型

    numpy float转int_python字符串转float类型查看数据类型print(image.dtype)unit8转换成float32先将图片转化为float32类型,再除以255,得到0-1之间的数importnumpyasnpimage=image.astype(np.float32)/255float32转换成uint8每个数乘以255,再转化为uint8importnumpyasnpimage=(image*255).astype(np.uint8)…

    2025年12月12日
    6

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号