彻底理解js中的闭包

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

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

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

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

 

我们首先知道闭包有3个特性:

①函数嵌套函数

②函数内部可以引用函数外部的参数和变量

③参数和变量不会被垃圾回收机制回收

 

本文我们以闭包两种的主要形式来学习

 

①函数作为返回值

彻底理解js中的闭包

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

再来看一个闭包的经典例子

彻底理解js中的闭包

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

 

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

写一个for循环,让它按顺序打印出当前循环次数

彻底理解js中的闭包

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

 

彻底理解js中的闭包

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

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

彻底理解js中的闭包

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

 

②闭包作为参数传递

彻底理解js中的闭包

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

 

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

好处

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

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

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

坏处

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

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

 

 

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

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

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • ORACLE优化器

    一ORACLE优化器概述ORACLE优化器是用于生成SQL语句访问数据库时使用的执行计划的。ORACLE优化器通过使用ORACLE搜集的关于数据库对象的统计数据来生成SQL语句的访问计划(使用什么对象)并执行计划(使用何种操作)    二ORACLE优化器的分类 ORACLE优化器分为三类:1)RULE优化器:基于规则的优化器相对比较简单,通过检查数据库的

    2022年4月7日
    42
  • Linux环境下安装部署redis「建议收藏」

    Linux环境下安装部署redis「建议收藏」目录一、下载安装包二、安装redis2.1下载安装最新版的gcc编译器2.2上传安装包至/opt目录2.3解压命令2.4解压完成后进入目录2.5执行make命令2.6如果没有准备好C语言编译环境,执行make命令会报错2.7解决方案:运行makedistclean2.8然后再redis-6.2.6目录下再次执行make命令2.9跳过maketest继续执行:makeinstall3.0安装目录/usr/local/bin.

    2022年10月4日
    0
  • ubuntu-cuda卸载[通俗易懂]

    ubuntu-cuda卸载[通俗易懂]不小心用sudoaptuninstallnvidia-cuda-toolkit安装了cuda,安装的是7.5发现,卸载sudoapt-getremove–auto-removenvidia-cuda-toolkit

    2022年9月5日
    3
  • xShell连接vmware虚拟机【经典】[通俗易懂]

    在刚刚开始学习Linux的同学,在VMware安装好Linux之后,不知道怎么去设置Ip,通过xshell去和虚拟机进行连接,下面就是我自己学习时候总结的连接方法,希望大家在连接后好好学习,我们一起进步。我的配置环境是VMware8,安装的是centOS6.3,使用的是Xshell5.l在虚拟机安装好Linux如图:1:输入 setup 回车,看到下面的界面,选择Network …

    2022年3月1日
    1.1K
  • RSA加密算法简介[通俗易懂]

    RSA加密算法简介[通俗易懂]背景RSA加密算法是公钥密码最著名的算法之一,是由MIT三位(RonRivest,AdiShamir,LenAdleman)提出的,也就以三位的名字首字母命名。该算法的理论基础是“大数分解和素数检测“,如果说有一天,大数分解和素数检测的数学理论被证明可以简单解决,那么RSA算法的加密将没有任何意义。有提出说量子计算机的出现可以大大提高RSA的破解效率。下面我们将简单学习RSA加密算法的

    2022年5月3日
    109
  • 什么是itp_常见的培训类型

    什么是itp_常见的培训类型PMP培训知识体系中,项目管理信息系统PMIS是个经常出现的工具和技术,它即属于事业环境因素,会制定我们项目的规划和其它工作,同时也是工具和技术,我们需要依靠和借助PMIS完成很多工作的实际操作,很多

    2022年8月5日
    3

发表回复

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

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