闭包的定义
在 简单理解JS中的闭包 通过阮一峰老师关于闭包的文章写过一次对闭包的理解,这篇文章比较简洁地再谈一次闭包。
闭包指的是能够访问另一个函数作用域中变量的函数。
闭包的作用
1)闭包使得我们可以在函数的外部访问函数内部的变量
function fn1 () {
let a = 1
return function fn2 () {
console.log('fn1 中的 a = ', a)
}
}
let result = fn1()
result() // fn1 中的 a = 1
如上面的代码所示,在函数外部我们本来是不能访问 fn1 内部的变量 a 的,但是通过闭包 fn2 这座桥梁,现在我们可以在函数 fn1 的外部访问到其内部的变量了。
2)闭包的另一个主要作用是能够隐藏数据
看下面这段代码
function cache () {
let data = {}
return {
get(key) {
return data.key
},
set(key, val) {
data.key = val
}
}
}
// 使用 get 和 set 可以访问和修改 data 对象但是拿不到 data 对象
const result = cache()
result.set('a', 1)
console.log(result.get('a'))
上面的代码中 get 和 set 就是两个闭包,可以访问到 cache 内部的变量 data,借助这两个闭包(桥梁)也能在函数外部访问到这个变量,并且能够修改 data 对象内部的值。但是并不能获取到 data 对象,这就是闭包常见的一个应用隐藏变量。
闭包带来的问题
再来分析一下上面的这段代码,一般情况下当一个函数运行完成之后这个函数内部的变量就会被销毁,但是在使用闭包后,cache 函数内部的变量 data 并不会被销毁而是永远保留在内存中。
这是因为外部的 result 引用着返回的对象,对象中又有 get 和 set 函数里面使用着 data,所以当 cache 运行完成之后也是有变量在引用它,因此并不会被垃圾回收机制回收。
所以要在闭包使用完成后及时手动地释放引用,例如将上面的 result 赋值为 null,这个时候 cache 函数内部的 data 对象就没有变量再去引用它了,因此会被垃圾回收机制回收。