闭包(closure)指有权访问另一个函数作用域中变量的函数。
闭包的作用:
闭包案例1
function fn1() {
var num = 10;
function fn2() {
console.log(num);
}
fn2();
}
//输出结果:10
fn1();
fn2
的作用域当中访问到了 fn1
函数中的 num
这个局部变量。
闭包案例2
另一个例子:
function fn() {
var num = 10;
return function() {
console.log(num);
}
}
var f = fn();
// 上面这步类似于
// var f = function() {
// console.log(num);
// }
//输出结果:10
f();
在上例中我们做到了在 fn()
函数外面访问 fn()
中的局部变量 num
。闭包延伸了变量作用域范围,读取了函数内部的变量。
闭包案例3
const fn = function() {
let sum = 0
return function(){
sum++
console.log(sum);
}
}
/**
* `fn()` 进行 `sum` 变量申明并且返回一个匿名函数,
* 第二个 `()` 意思是执行这个匿名函数
*/
fn()() // 1
fn()() // 1
我这里直接简单解释一下,执行 fn()()
后,fn()()
已经执行完毕,没有其他资源在引用 fn
,此时内存回收机制会认为 fn
不需要了,就会在内存中释放它。
那如何不被回收呢?
const fn = function() {
let sum = 0
return function(){
sum++
console.log(sum);
}
}
fn1 = fn()
// 1
fn1()
// 2
fn1()
// 3
fn1()
这种情况下,fn1
一直在引用 fn()
,此时内存就不会被释放,就能实现值的累加。那么问题又来了,这样的函数如果太多,就会造成内存泄漏。
内存泄漏了怎么办呢?我们可以手动释放一下。
const fn = function() {
let sum = 0
return function(){
sum++
console.log(sum);
}
}
fn1 = fn()
// 1
fn1()
// 2
fn1()
// 3
fn1()
// `fn1` 的引用 `fn` 被手动释放了
fn1 = null
// `num` 再次归零
fn1 = fn()
// 1
fn1()