浅谈闭包

闭包是什么

词法作用域

先要了解什么是词法作用域

  • 作用域是由书写代码时候函数的位置决定的
  • 可以想象函数里面嵌套函数,最里面函数可以方面函数的变量
  • 也就是说内部函数可以读取外部函数的变量
  • 但是我们外部怎么访问内部的局部变量,这就需要闭包
1
2
3
4
5
6
7
8
9
10
//如果我们在外部想拿到n的变量,可以函数内部返回
//
function f1() {
let n = 999;
function f2() {
return n;
}
return f2;
}
let n = f1()();
  • 函数可以记住并访问它所在的词法作用域,换言之,它记住了定义时候的位置
  • 然后它在其他作用域执行的时候,带上了它的词法作用域,这就是闭包

闭包可以干什么

很多高级应用都需要用到闭包来实现,主要用处有三个

  • 上面提到的,可以访问内部函数变量
  • 保持内部变量在内存之中
  • 私有变量和模块化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
function f1() {
var n = 999;

nAdd = function() {
n += 1;
};

function f2() {
alert(n);
}

return f2;
}

var result = f1();

result(); // 999

nAdd();

result(); // 1000
//私有变量和模块化
var monitor = (function() {
var imgs = [];
return function(src) {
var img = new Image();
imgs.push(img);
img.src = src;
};
})();
  • 因为 f1 是 f2 的父函数,f2 依赖于 f1 的存在,f2 被赋给了全局变量,所以垃圾回收机制不会回收
  • 因为 f2 不回收,所以 f1 也会存在于内存之中
  • n 的变量就静静呆在内存之中
  • 比如 add(1)(2)(3)=6 就是这样解的

闭包的问题

  • 闭包会导致变量都保存在内存里面,所以大量闭包会导致性能问题。遇到可以不用的,设置为 null,通知垃圾回收机制回收。