ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

JavaScript 重中之重的难点————闭包

2022-07-02 13:02:47  阅读:168  来源: 互联网

标签:闭包 难点 函数 作用域 JavaScript 内存 全局 变量


JavaScript 重中之重的难点————闭包

一、作用域链:

  首先推荐B站一个视频,视频从作用域链、生命周期、块级作用域、到闭包讲的十分全面:https://www.bilibili.com/video/BV1YJ411R7ap?p=3&spm_id_from=pageDriver&vd_source=452bb044f96afbbf26944f5c6904defd

  现在开始,了解闭包之前必须要了解明白JavaScript作用域的划分。

  1.作用域:变量和函数的可访问范围,控制着变量和函数的可见性与变量的作用范围。

  2.全局作用域:网页中所有脚本和函数均可使用。

   全局变量即拥有全局作用域的变量,即使页面没有调用使用,也不会被回收机制清除,而是继续存在于内存中,只有浏览器关闭时候才会清空。

  3.局部作用域:只能在定义的函数内使用。

          局部变量即在定义函数内可以调用使用的变量,函数调用结束之后就会清空,下次调用在重新开辟内存空间

  举一个例子:定义两个变量 一个全局a 一个局部b。

 

 

 

 

 

  可以根据结果看出,在全局环境中如果调用输出局部变量会报错:子用父可以,父用子不行。

  在举一个新例子:嵌套函数 更加深层次嵌套,如果想要输出b的累加

 

 

 

 

 

 

  根据结果可以清除看到,局部变量b每次都要重新开辟内存空间,之前的b就被回收删除了。

 

 

 

 

 

 

   那么现在想实现一次b的累加 如何做到,如果可以让b每次都不清空,保存在内存之中不动,跳过重新开辟内存这一步骤,是不是就可以完成累加。

  如果在全局中设定一个变量,用来存放xx()一直调用,那么回收机制就不会触发,也就不会重新开辟内存。

  而经过ax调用yy(),同级变量b并不会被清空销毁,而是同时保存在内存中。即这就是闭包。

 

 二、闭包:

  1.定义:闭包函数是声明在另一个函数内的函数,是被嵌套在父函数内部的子函数。

  而在《JS高级程序设计-第3版》中对闭包解释是:"闭包是指有权访问另外一个函数作用域中的变量的函数." 闭包函数可以访问[包裹其的函数]内的各种参数和变量,即便外部函数已经执行完毕。

  看不懂太乱对不对。那么就用人话解释一下。函数可以访问其他函数内的变量就称为闭包。

  上述例子当中,子函数yy() 可以访问父级函数当中变量b,即为闭包特性之一。

  2.闭包作用:

    • 使外部得以访问函数内部的变量;
    • 避免全局变量的使用,防止全局变量污染
    • 让某些关键变量得以常驻内存,免于被回收销毁

  3.闭包缺点:由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

  4.闭包应用:使用场景 : 防抖、节流、函数套函数避免全局污染等。

三、闭包应用场景:

  1.获取区间:例如在一串数组中获取一个区间之间的数字。

 

 

  其原理正是闭包原理。内部子函数可以调用外部父函数between内部的变量a和b。也可以应用到商品价格区间等。

  2.防抖:防抖是经常出现在js动画中的概念,好多萌新都不了解什么是防抖。其实顾名思义防止抖动。那么为什么动画会出现抖动?

  假设现在制作一个动画,一个按钮点击之后就缓慢向右移动。代码如下,可以很简单的实现效果

 

  但现在存在一个问题,如果点击多次按钮,就会出现按钮抖动(原谅我截图没办法体现抖动的状态。)就好像花屏一样。那么为什么会出现这种情况?

  首先,当你点击一次按钮,触发了事件之后,已经在内存当中开辟了一块区域让你存放。但是当你点击第二次,由于 left 是局部,所以还会开辟第二块区域。结果每次点击都产生新的left 就会造成抖动效果。

 

 

  那么如何避免,就像上面提到如何累加的案例一样,如果让left不在重新产生,而是一直存放在内存中,就可以完美解决了。

  最简单的办法就是,将left设置为全局属性,这样就一直存放在内存中。

 

 

  随之而来就出现另一个问题,当你再次连续点击按钮,虽然不会出现抖动效果,但是会产生按钮加速向前的效果。这是因为每次点击按钮,都产生一个定时器,而left 变成全局之后,定时器就变成了一个类似于叠加的效果,所以导致动画加速。那么就要将定时器设定为,只有第一次才会触发,直到动画结束。添加一个全局变量,在通过if判断。

 

 

   但是变量都设定为全局会导致,全局变量污染,加剧内存负担。所以就可以将left 放入 判断里面。

 

 四、总结:

  讲的可能不是特别全面,个人自身也是萌新小白,只能慢慢摸索去学,希望大家都比昨天的自己进步一点。

标签:闭包,难点,函数,作用域,JavaScript,内存,全局,变量
来源: https://www.cnblogs.com/WangEDblog/p/16436111.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有