关于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)
上一篇 2025年9月16日 下午7:01
下一篇 2025年9月16日 下午7:22


相关推荐

  • js判断类型

    js判断类型1 instanceof 运算符判断类型 functionAaa 父类 this name 小明 leta newAaa letstr newString asd letstr2 asdf letobj name 小明

    2026年3月19日
    2
  • java递归函数详解_java保存递归结果

    java递归函数详解_java保存递归结果一、递归函数,通俗的说就是函数本身自己调用自己…如:n!=n(n-1)!你定义函数f(n)=nf(n-1)而f(n-1)又是这个定义的函数。。这就是递归二、为什么要用递归:递归的目的是简化程序设计,使程序易读三、递归的弊端:尽管非递归函数效率高,但较难编程,可读性较差。递归函数的缺点是添加�了系统开销,也就是说,每递归一次,栈内存就多占用一截四、递归的条件:需有完毕任务的语句,需满足递归的要求…

    2026年1月18日
    5
  • mysql months_between_months_between()用法「建议收藏」

    mysql months_between_months_between()用法「建议收藏」orcl中months_between()函数用法如下:格式:即MONTHS_BETWEEN(日期1,日期2)例如:selectmonths_between(to_date(‘2018-10-9′,’yyyy-mm-dd’),to_date(‘2017-10-09′,’yyyy-mm-dd’))mfromdual;注:M:月selectmonths_between(to_date(’20…

    2022年7月12日
    16
  • 通俗易懂的讲解二极管三极管工作原理

    通俗易懂的讲解二极管三极管工作原理本文转自 https www zhihu com question https blog csdn net a10615 article details 先讲解二极管工作原理 白话文讲解这个确实不是一两句话说得清的 但是我还是想挑战一下自己的文字功底 尽量不用太理论化的陈述 话说世界上有种神奇的物质叫 半导体 这个题主肯定知道了 半导体我们通常使用的是硅

    2026年3月26日
    2
  • 通达OA 工作流执行出现的异常现象处理(图文)

    通达OA 工作流执行出现的异常现象处理(图文)一个朋友用的工作流,突然说这里面多了很多人不应该看到这个流程的,就是在查询工作时,最上面多了一个“查阅信息”项,然后最下面多了很多人查询的记录。这个项目是从哪里来的呢?普通的流程倒也无所谓了,而有些流程如发文、任职等还是需要保密的,这样让大家查阅肯定是不行的。一开始以为是使用了工作流的转存文件柜的功能,实验了一下,这样转存后并不会在流程里关联查看到查阅信息。又实验了一下转发布公告,同样不是。最后咨

    2022年6月23日
    41
  • Merkle Tree 概念

    Merkle Tree 概念

    2021年6月18日
    121

发表回复

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

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