闭包closure
定义
function A() { let a = 1 function B() { console.log(a) } return B }
• 堆内存 二级缓存
• 闭包是由函数以及声明该函数的词法环境组合而成的。
• 函数 A 返回了一个函数 B,并且函数 B 中使用了函数 A 的变量,函数 B 就被称为闭包。
• 闭包是指有权访问另一个函数作用域内变量的函数,创建闭包的最常见的方式就是在一个父函数内创建一个新的子函数,子函数可以访问到父函数里的局部变量。
• 简单说就是 定义在一个函数内部的函数,内部函数持可以引用外部函数 内的变量 或 参数的引用。 内部函数依赖外部函数, 外部函数参数和变量 不会被垃圾回收机制回收,这些变量会始终存在于内存中。 可以读取函数内部的变量,可以避免全局变量的污染,坏处会增加内存的使用量,容易导致内存泄漏,解决方法就是退出函数前,将不适用的局部变量全部删除。在 JavaScript 中,函数即是闭包。
• 一个父函数里面包含了一个子函数,子函数调用了父函数内部的变量,如果子函数在外部被调用,就产生了闭包。简单的说,闭包就是能够读取其他函数内部变量的函数。
• 在 JavaScript 中,根据词法作用域的规则,由于作用域链,内部函数总是可以访问其外部函数中声明的变量,当通过调用一个外部函数返回一个内部函数后,即使该外部函数已经执行结束了,但是内部函数引用外部函数的变量依然保存在内存中(因为引用,所以没被内存垃圾回收),我们就把这些变量的集合称为闭包。
闭包形成的条件
- 函数嵌套
- 内部函数引用外部函数的局部变量
作用
- 避免全局变量的污染
- 读取函数内部的变量
- 让这些变量的值始终保持在内存中。不会在 f1 调用后被自动清除。
- 实行封装 私有属性,闭包的第一个用途是使我们在函数外部能够访问到函数内部的变量。通过使用闭包,我们可以通过在外部调用闭包函数,从而在外部访问到函数内部的变量,可以使用这种方法来创建私有变量。
缺点
- 使用过多的闭包会消耗大量内存,造成网页的性能问题,可以在函数执行完成之前把不需要的局部变量删除。 在退出函数之前,将不使用的局部变量全部删除
使用场景
- Redux -> Store 原理,store 的实现原理比较简单,就是根据传入的初始值来创建一个对象。利用闭包的特性来保留这个 store,允许通过 getState 来获取到 store。
之所以通过 getState 来获取 store 是为了获取到当前 store 的快照,这样便于打印日志以对比前后两次 store 变化,方便调试。
const createStore = (reducers, initialState, enhancer) => { let store = initialState; const getState = () => store; return { getState } }
- 柯里化 模块化
- React -> 函数组件 -> useState -> 闭包缺陷
- 防抖
- 节流
- setTimeout 传参
for (var i = 1; i <= 5; i++) { setTimeout(function() { console.log(i); }, 10) } for (var i = 1; i <= 5; i++) { (function(j) { setTimeout(function timer() { console.log(j); }, 10) })(i) }
问答
- 什么是闭包?闭包就是同时含有对函数对象以及作用域对象引用的最想。实际上,所有 JavaScript 对象都是闭包。
- 闭包是什么时候被创建的?因为所有 JavaScript 对象都是闭包,因此,当你定义一个函数的时候,你就定义了一个闭包。
- 闭包是什么时候被销毁的?当它不被任何其他的对象引用的时候。
如何清除闭包
- 手动清除,将用完的函数或者变量置为 null。
参考链接
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures
http://edubook.bluej.cn/js/docs/
https://zhuanlan.zhihu.com/p/363055656
https://blog.csdn.net/The_upside_of_down/article/details/83240092
https://juejin.cn/post/6844903986508611597
https://juejin.cn/post/6858052418862235656
https://blog.csdn.net/qq_39903567/article/details/115010640
https://zhuanlan.zhihu.com/p/307911919
https://www.cnblogs.com/formercoding/p/5884735.html
http://blog.leapoahead.com/2015/09/15/js-closure/
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论