谈到闭包就需要先了解JavaScript的作用域原理,在ES5以及之前的版本中,大括号{}
是不能形成单独的作用域的,即在全局作用域中
var a = 10;
{
var b = 10;
}
a
和b
都是全局变量,而在JavaScript中的私有作用域都是定义在函数里面的变量,在函数里面定义的变量才是私有的,同时,在函数运行时形成的私有作用域可以访问外部作用域定义的变量,即
var a = 10;
var fn = function() {
a++;
var b = 11;
console.log(a + b)
}
fn() // => 22
console.log(a) // 11
这里可以看出函数fn访问并修改了全局变量a的值。
而函数执行形成的私有作用域会在执行完毕后被销毁,也就是说fn执行后,fn形成的私有作用域会被销毁,里面定义的局部变量b
会被销毁。
如果想要里面定义的私有变量不被销毁,就需要在外部有对该作用域的引用。
在上述代码中,函数fn没有明确的定义返回值,所以函数执行后会返回undefined,
如果定义了返回值是一个函数呢?.
var fn = function() { // 私有作用域AA
var a = 10;
return function() { // 私有作用域BB
a++;
console.log(a);
}
}
fn() // 11
fn() // 12
可以看到函数fn两次的执行结果分别为11和12,看得出外部变量a的值被修改了,而且并没有随着执行完毕形成的私有作用域被销毁,反而可以一直保存了下来,这就是闭包的实现方式了,如果我们把上述代码所形成的私有作用域起个名,外部作用域为AA,内部作用域为BB,那么在函数fn执行后,作用域AA不会被销毁,这就是闭包的实现了。