闭包是指有权访问另一个函数作用域中的变量的函数。创建闭包的常见方式,就是在一个函数内部创建另一个函数。
1. 闭包
例子1:
function a(){
var n = 0;
function inc() {
n++;
console.log(n);
}
inc();
inc();
}
a(); //控制台输出1,再输出2
内部的函数inc访问了外层函数a的变量n,所以inc是一个闭包。
例子2:
function a(){
var n = 0;
function inc(){
n++;
console.log(n);
}
return inc;
}
var c = a();
c(); //控制台输出1
c(); //控制台输出2
注意:调用a()返回的是一个函数名,此时c=函数,()才是执行函数
陷阱:
function count() {
var arr = [];
for (var i=1; i<=3; i++) {
arr.push(function () {
return i * i;
});
}
return arr;
}
var results = count();
var f1 = results[0]; //16
var f2 = results[1]; //16
var f3 = results[2]; //16
当for循环执行完,i的值已经是4,所以数组里面的每个函数使用的外部函数的i值就是4.
解决这个陷阱要使用匿名函数:
function count() {
var arr = [];
for (var i=1; i<=3; i++) {
arr.push((function (n) {
return function () {
return n * n;
}
})(i));
}
return arr;
}
var results = count();
var f1 = results[0];
var f2 = results[1];
var f3 = results[2];
2. 匿名函数
注意这里用了一个“创建一个匿名函数并立刻执行”的语法:
(function (x) {
return x * x;
})(3); // 9
3. 闭包的作用
用于访问私有变量的公有方法
函数中定义的变量,都可以认为是私有变量,因为不能在函数外部访问这些变量。如果在这个函数内部创建一个闭包,那么闭包通过自己的作用域链也可以访问这些变量。利用这一点,就可以创建用于访问私有变量的公有方法。
function create_counter(initial) {
var x = initial || 0;
return {
inc: function () {
x += 1;
return x;
}
}
}
外层函数定义了自己的私有变量x,返回了一个可以访问x的闭包inc。
闭包就是函数返回的访问私有变量的公用接口。用起来就像这样:
var c1 = create_counter();
c1.inc(); // 1
c1.inc(); // 2
c1.inc(); // 3
var c2 = create_counter(10);
c2.inc(); // 11
c2.inc(); // 12
c2.inc(); // 13 ,并不能随便改变x的值,只能按闭包定义的方式去访问改变。