什么是闭包?作用?
函数与对其状态即词法环境(lexical environment)的引用共同构成闭包(closure)。也就是说,闭包可以让你从内部函数访问外部函数作用域。在JavaScript,函数在每次创建时生成闭包。
闭包常常用来间接访问一个变量
1.闭包
闭包是由函数以及创建该函数的词法环境组合而成。这个环境包含了这个闭包创建时所能访问的所有局部变量。
function makeFunc() {
var name = "Mozilla";
return function displayName() {
return name;
}
}
var myFunc = makeFunc(); //myFunc 就是个闭包
console.log(myFunc()); // Mozilla
2.闭包简单使用
在面向对象编程中,对象允许我们将某些数据(对象的属性)与一个或者多个方法相关联。
var Counter = (function() {
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
}
})();
console.log(Counter.value()); // 0
Counter.increment();
Counter.increment();
console.log(Counter.value()); //2
Counter.decrement();
console.log(Counter.value()); //1
3.在循环中创建闭包:一个常见错误
循环早已执行完毕,arr ( 被三个闭包所共享)arr[0]已经等于了 arr的最后一项的值
function foo(){
var arr = [];
for(var i = 0; i < 2; i++){
arr[i] = function(){
return i;
}
}
return arr;
}
var bar = foo();
console.log(bar[0]()); //2
解决方法以下
方案一:使用更多的闭包
function foo(){
var arr = [];
for(var i = 0; i < 2; i++){
arr[i] = makeCallback(i)
}
return arr;
}
var bar = foo();
console.log(bar[0]()); //0
function makeCallback(i) {
return function(){
return i;
}
}
方案二:避免使用过多的闭包,可以用let关键词
function foo(){
var arr = [];
for(let i = 0; i < 2; i++){
arr[i] = function(){
return i;
}
}
return arr;
}
var bar = foo();
console.log(bar[0]()); //0
- 性能考量
如果不是某些特定任务需要使用闭包,在其它函数中创建函数是不明智的,因为闭包在处理速度和内存消耗方面对脚本性能具有负面影响。
- 可以用闭包模拟私有方法
比如 Java,是支持将方法声明为私有的,即它们只能被同一个类中的其它方法所调用。而 JavaScript 没有这种原生支持,但我们可以使用闭包来模拟私有方法。具体见https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures
参考网页:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures
https://zhuanlan.zhihu.com/p/22486908