什么是闭包
闭包是JavaScript特有的一种函数嵌套结构,打破了作用域链的规则,是能够读取其他函数内部变量的函数,
本质:定义在函数内部的函数(函数嵌套函数),将函数内部和函数外部连接起来的一个桥梁。
原理:形成闭包结构时,内存函数引用外层函数的局部变量,新形成的作用域叫做闭包(closure)作用域。闭包会一直在栈中被挂起,生成一个不被销毁的函数空间变量常驻内存 直到手动销毁。
销毁闭包:当一个对象没有被引用时会被垃圾回收机制回收,而销毁闭包的方式就是赋值为null
。
形成闭包的三个条件:
- 函数嵌套函数(至少两个函数)
- 在内层的函数中使用外层函数的局部变量或参数
- 内层函数作为返回值返回
用途:
- 希望一个变量常驻在内存中(延长变量作用域、生命周期),使已经运行结束的函数中的变量对象继续保留在内存中,因为闭包函数保留这个变量的引用,所以这个变量对象不会被不会被垃圾回收机制回收 GC
- 使我们在函数外部能够访问到函数内部的变量。通过在外部调用闭包函数,从而在外部能够访问到函数内部的变量
- 避免全局变量污染
缺点:
- 概念复杂不易理解
- 占用过多系统资源(内存),大量滥用闭包可能造成
栈溢出
IE->(内存泄漏) - 功能被模块化开发取代(模块化是以闭包为基础构建的)
关于闭包会造成内存泄漏?知乎一位网页的看法:
js闭包测试
使用场景:
- 通过循环在页面上多个dom节点绑定事件
- 封装私有变量(计时器) 自执行的匿名函数保存循环变量
- 延续局部变量的寿命
- 高阶组件
- 函数防抖 用于记录一个计时器
沙箱模式
一种设计模式:解决特定问题给出的简洁而优化的解决方案
解决:变量私有化以后的访问和操作
利用闭包 把所有函数或者属性 变量都放在一个函数内部
面试题
函数默认行为:
- 定义函数
在堆里开辟一个空间,将函数体内的代码存入
把空间地址赋值给栈里面的变量(函数名)
- 调用函数
按照存储的地址找到函数存储空间
在调用栈 开辟一个 函数执行空间 在函数执行空间里进行形参赋值和预解析(先形参赋值再预解析)
把函数存储空间里的代码复制一份给函数执行空间执行
代码执行完毕,这个新开辟的函数执行空间销毁
function closure(i = 0) {
return function (n) {
console.log(n + i++)
}
}
var foo = closure();
var bar = closure(1)
foo(1)
closure(2)(3)
bar(4)
closure(4)(5)
bar(5)
foo(6)
console.log(i)