1. 定义:
函数对象可以通过作用域链相互关联起来,函数体内部的变量都可以保存在函数作用域内。
——《JavaScript前端指南》
2. 理解:
闭包给函数访问外部函数内的局部变量创造了条件,其实就是转换函数内局部变量的作用域链,使得该变量可是被外部函数引用及操作。闭包可以捕捉到局部变量(或参数),并将其一直传承下去。
3. 案例:
var scrop = 'global scrop'; //全局变量
function checkScrop(){
var scrop = 'local scrop'; //局部变量
function f(){ return scrop}; //在作用域内输出变量
return f; //返回的是函数对象,不同于return f()返回的调用结果
}
checkScrop()() //返回的是‘local scrop’
//计时器案例
function counter(){
var n = 0;
return {
count:funtion(){return n++},
reset:function(){n=0}
};
}
var c = counter(),d=counter();
c.count();
b.count();
c.reset();
c.count();
b.count();
//n的值依次是 1 , 1 , 0 ,1 ,2 因为两个计时器是互相不干扰的,但是同一个计时器内部的 reset() 和 count()方法是共享的。
4. 闭包及垃圾回收之间的关系:
每次调用JavaScript函数的时候,都会为之创建一个新的对象用来保存局部变量,把这个对象添加至作用域链中。当函数返回的时候,就从作用域链中将该对象删除。
- 如果不存在嵌套的函数,也没有其他引用指向这个绑定对象,它就会被当作垃圾回收掉。
- 如果定义了嵌套函数,每个嵌套函数都各自对应一个作用域链,并且这个作用域链指向一个变量绑定对象。但如果这些嵌套的函数对象在外部函数中保存下来了,那么它们也会和所指向的变量绑定对象一样当垃圾回收。
- 但如果这个函数定义了嵌套的函数,并将它作为返回值返回或者存储在某处的属性中,这时就会有一个外部引用指向这个嵌套的函数,它就不会被当做垃圾回收,并且它所指向的变量绑定对象也不会被当作垃圾回收(即闭包)。
5. 常见使用作用范围:
创建私有变量