定义
一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包(closure)。
闭包:函数 + 可以访问的自由变量
普通函数:如果它可以访问外层作用于的自由变量,那么这个函数就是一个闭包;
广义的角度:JavaScript中的函数都是闭包;
狭义的角度:JavaScript中一个函数,如果访问了外层作用于的变量,那么它是一个闭包;
出自于 coderwhy 大佬
作用:
1、实现数据私有
let count = 0
function fn () {
count++
console.log('fn函数被调用了' + count + '次')
}
fn() // count数据容易被修改
fn()
fn()
count = 10
fn() // fn函数被调用了11次
-------------------------------------------------------------
function fn () {
let count = 0
function add () {
count++
console.log('fn函数被调用了' + count + '次')
}
return add
}
const addFn = fn()
addFn() // fn函数被调用了1次
addFn() // fn函数被调用了2次
addFn() // fn函数被调用了3次
count = 10
addFn() // fn函数被调用了4次
2、解决 var 的全局变量在异步函数调用中的变化
for (**let** i = 0; i < 5; i++) { // let 是局部变量
setTimeout(() => {
console.log(i);
}, 1000 * i);
}
//输出:0 1 2 3 4
for (**var** i = 0; i < 5; i++) { // var 是全局变量
setTimeout(() => {
console.log(i);
}, 1000 * i);
}
// 输出: 5 5 5 5 5,5是因为最后i++跳出来的是5
// 使用闭包实现类似let的结果
for (var i = 0; i < 5; i++) {
function f(i) {
setTimeout(() => {
console.log(i);
}, 1000 * i);
}
f(i);
}
//输出:0 1 2 3 4
3、让这些变量的值始终保持在内存中,不被销毁
注意点:外部函数中,一般需要return来进行引用(内存才不会被释放)
销毁的方法:
- 标记清除:从根部,全局出发,访问不到(无法触及)的内存空间,就会被自动回收
- 释放内存,断开了对于之前内部函数的引用,对应的缓存的变量内容也会被释放掉
Reference
你不可不知道的 JavaScript 作用域和闭包 - 知乎 (zhihu.com)
学习Javascript闭包(Closure) - 阮一峰的网络日志 (ruanyifeng.com)