网站首页 > 技术文章 正文
更多技术分享,点击右上角红色的"关注",感谢你的支持!
闭包基本的概念
闭包并不是JavaScript特有的,在PHP、Scala、Groovy、Ruby、 Python、swift 以及Java(Java8及以上)等很多语言中,都有对闭包特性的支持。
简单来说,闭包就是能够读取其他函数内部变量的函数。例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。
在本质上,闭包是将函数内部和函数外部连接起来的桥梁。
只看这些概念,是不是有点蒙圈了,别急,且往下看。
结合代码来说明
如果一个函数a定义在另一个函数b里面,那么,这个函数a就是一个闭包。
重要的关键点,函数a能够直接读取函数b中定义的变量,这个就是闭包的特性
再来一段有意思的代码例子:
函数b这次不再直接执行a了,而是直接返回了函数a,所以func本质上是对函数a实例的引用,
而func()竟然能记住x,这就是JavaScript的闭包机制的神奇之处。
到这里,我们结合以上代码说明,闭包就是函数a和变量x。
闭包可以用来做什么
工作中,不知不觉,我们其实经常用到闭包,比如下面这个例子,一个初始化函数里面包含一个按钮点击事件:
另一个具体点的例子,一段发送验证码的Demo:
可以看到,在onclick函数里面,是可以正常操作time_wait和time_left变量的,细心的朋友可能已经发现,
代理里边已经出现两个闭包的应用了,一处是onclick,还有一处就是setInterval这个定时函数。
我们再想想,为什么要用闭包?什么场景需要呢?
JavaScript语言特性需要(setTimeout、setInterval...)
事件绑定需要(onclick...)
还有一个重要的原因,那就是OO思想,把上面发送验证码的代码改造一下来看看
这样,已经变成面向对象的编程风格了。
什么时候不该用闭包
注意了朋友,不要为了秀技巧,到处使用闭包。因为滥用闭包可能会导致脚本执行缓慢,以及消耗不必要的内存。尤其是以下两种情况时,应该尽量避免。
1.循环
页面上测试,你会发现无论你点击哪个按钮,都会弹出4,因为click函数是个闭包,页面加载后循环开始执行,当你点击按钮的时候,循环已经执行完了,此时i值为4,而闭包记得它周围的变量,所以弹出的都是4。
要解决这个问题,可以把打印的代码提炼到另一个函数里面,这样就会产生一个新的作用域:
或者用立即执行函数表达式:
2.构造器
方法应该关联于对象的原型,而不要定义到对象的构造器中。原因是这将导致每次对象实例化时,方法都会被重新定义一次。
应该这样改写,让继承的原型可以为所有实例共享:
结论
闭包就是一个函数引用另外一个函数的变量,因为变量被引用着所以不会被回收,因此可以用来封装一个私有变量。这是优点也是缺点,不必要的闭包只会徒增内存消耗!另外使用闭包也要注意变量的值是否符合你的要求,因为他就像一个静态私有变量一样。闭包通常会跟很多东西混搭起来,接触多了才能加深理解,这里只是开个头说说基础性的东西。
猜你喜欢
- 2024-10-24 Service Workers - JS API 简介(servicedescriptor)
- 2024-10-24 web性能优化的15条实用技巧(web应用性能优化思路)
- 2024-10-24 如何在 Service Worker 重新启动时重用信息
- 2024-10-24 Python在selenium里面注入JavaScript程序的方法
- 2024-10-24 requireJS 实战(requirejs define)
- 2024-10-24 面试妥了!2020 爬虫面试题目合集(爬虫面试经历)
- 2024-10-24 Nest.js 从零到壹系列(一):项目创建&路由设置&模块
- 2024-10-24 JS小知识,分享 7 个高频的工具函数,也许你用的上
- 2024-10-24 如何使用Playwright优化测试性能(play—player)
- 2024-10-24 JavaScript开发人员都应知道的异步迭代,你会了吗?
- 11-26Win7\8\10下一条cmd命令可查得笔记本电脑连接过的Wifi密码
- 11-26一文搞懂MySQL行锁、表锁、间隙锁详解
- 11-26电脑的wifi密码忘记了?一招教你如何找回密码,简单明了,快收藏
- 11-26代码解决忘记密码问题 教你用CMD命令查看所有连接过的WIFI密码
- 11-26CMD命令提示符能干嘛?这些功能你都知道吗?
- 11-26性能测试之慢sql分析
- 11-26论渗透信息收集的重要性
- 11-26如何查看电脑连接过的所有WiFi密码
- 最近发表
- 标签列表
-
- cmd/c (57)
- c++中::是什么意思 (57)
- sqlset (59)
- ps可以打开pdf格式吗 (58)
- phprequire_once (61)
- localstorage.removeitem (74)
- routermode (59)
- vector线程安全吗 (70)
- & (66)
- java (73)
- org.redisson (64)
- log.warn (60)
- cannotinstantiatethetype (62)
- js数组插入 (83)
- resttemplateokhttp (59)
- gormwherein (64)
- linux删除一个文件夹 (65)
- mac安装java (72)
- reader.onload (61)
- outofmemoryerror是什么意思 (64)
- flask文件上传 (63)
- eacces (67)
- 查看mysql是否启动 (70)
- java是值传递还是引用传递 (58)
- 无效的列索引 (74)