关于js闭包

闭包

闭包就是(在外部?)引用特定的局部变量实例的功能;

闭包是函数和声明该函数的词法环境的组合,这个环境包含了这个闭包创建时所能访问的所有局部变量。——MDN

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures

闭包是指有权访问另一个函数作用域中的变量的函数。——《js高级程序设计第三版》

一般在js中,闭包用来在外部访问某一函数中的局部变量,该局部变量被保存在一个内部函数块中;如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function makeAdder(x) {
return function(y) {
return x + y;
};
}

var add5 = makeAdder(5);
/*
5被赋值给局部变量x,局部变量x被保存在闭包环境中
而闭包被赋值给add5,因此函数add5内还能继续使用x(=5)
*/
var add10 = makeAdder(10);

console.log(add5(2)); // 7
console.log(add10(2)); // 12

使用场景

  1. 通常使用只有一个方法的对象的地方,都可以使用闭包;(将数据与函数进行绑定的时候)

闭包很有用,因为他允许将函数与其所操作的某些数据(环境)关联起来。这显然类似于面向对象编程。在面向对象编程中,对象允许我们将某些数据(对象的属性)与一个或者多个方法相关联。——MDN

1
2
3
4
5
6
7
8
9
10
11
12
13
function makeSizer(size) {
return function() {
document.body.style.fontSize = size + 'px';
};
}

var size12 = makeSizer(12);
var size14 = makeSizer(14);
var size16 = makeSizer(16);

document.getElementById('size-12').onclick = size12;
document.getElementById('size-14').onclick = size14;
document.getElementById('size-16').onclick = size16;
  1. 模拟私有方法:即只有实例才能使用的方法,且不能直接修改对象的方法!(对比将方法绑定到this对象或原型prototype上,那样可以通过直接修改对象方法从而影响所有的实例!此谓之私有?)
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
var makeCounter = function() {
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
}
};

var Counter1 = makeCounter();
var Counter2 = makeCounter();
console.log(Counter1.value()); /* logs 0 */
Counter1.increment();
Counter1.increment();
console.log(Counter1.value()); /* logs 2 */
Counter1.decrement();
console.log(Counter1.value()); /* logs 1 */
console.log(Counter2.value()); /* logs 0 */

注意事项

如果不是某些特定任务需要使用闭包,在其它函数中创建函数是不明智的,因为闭包在处理速度和内存消耗方面对脚本性能具有负面影响。