关于JavaScript闭包理解

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

关于JavaScript闭包理解

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



在这里插入图片描述

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

在这里插入图片描述

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

按照预期它应该依次输出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

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

②闭包作为参数传递
在这里插入图片描述

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

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

好处

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

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

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

坏处

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

变量不能被销毁,增大了内存消耗,造成内存泄漏,解决方法是可以在使用完变量后手动为它赋值为null;

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

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

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

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


相关推荐

  • $(document).click() 在苹果手机上不能正常运行解决方案

    $(document).click() 在苹果手机上不能正常运行解决方案

    2021年11月5日
    57
  • Xshell 7 提示 “要继续使用此程序,您必须应用最新的更新或使用新版本”

    Xshell 7 提示 “要继续使用此程序,您必须应用最新的更新或使用新版本”Xshell7忽然不能用,提示“”要继续使用此程序,您必须应用最新的更新或使用新版本“”解决办法:修改电脑的系统时间。右下角日期-右键“调整日期/时间(A)”-手动设置日期和时间-将日期调整到2017年即可。之前Xshell6和Xshell5也会包这样的错误,是因为xshell比较傻叉,需要你强制更新到最近版本否则就不能使用。也解决办法就是找到xshell的解决目录,用UE打开nslicense.dll文件:xshell6和xshell5解决的具体步骤步骤1:下载U…

    2022年7月15日
    101
  • containsKey使用方法[通俗易懂]

    containsKey使用方法[通俗易懂]作用是判断Map中是否有所需要的键值,下面是具体的代码:

    2022年7月3日
    38
  • FSFS和VDFS存储方式的区别

    FSFS和VDFS存储方式的区别

    2021年9月19日
    55
  • 五种matlab读取excel文件方法

    五种matlab读取excel文件方法读取 excel 文件的五种方式 readcell filename 以 cell 元胞数组 注 访问 cell 元素用 格式导入所有信息 空格被识别为 missing 用 strcmp class references 2 3 missing 来判定 若为 1 则说明为空 最省事的方法 NUM TXT RAW xlsread filename NUM 返回的是 excel 中的数据 TXT 输出的是文本内容 RAW 输出的是未处理数据 一般情况下 我们直接用 reference xlsread exa

    2025年9月26日
    2
  • 大数据平台的元数据管理

    大数据平台的元数据管理【概念解释】1,大数据平台——是指服务于大数据计算或存储的平台,包括大数据的计算集群(hive、spark、flink、storm等等)和存储集群(如hadoop、hbase等等)。2,大数据平台涉及的元数据——由大数据作业的业务逻辑直接读写处理的业务数据,都不是元数据,除此之外的数据都是元数据。例如数据表的schema信息、任务之间的血缘关系、任务的权限映射关系、数据的业务属性、数据占用的磁…

    2022年5月8日
    57

发表回复

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

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