一.首先要了解JS中变量的作用域(全局变量和局部变量)
JS中通常函数可以直接读取外部的全部变量,但是无法读取函数外部其它函数中定义的局部变量
要注意在函数内部声明变量的时候要使用 var 关键字,如果不使用var关键字,则直接声明了一个全局变量
<span style="font-size:12px;">function add(){
i = 99;
alert(i);
}
add(); //输出99
function bbs(){
alert(i);
}
bbs();//输出99 其中bbs函数中的i调用的是函数add因为没有使用var关键字定义的全局变量</span>
二:闭包的概念
“官方”的解释是:所谓“闭包”,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。
function
a(){
var
i=0;
function
b(){
alert(++i);
}
return
b;
}
var
c=a();
c();//输出1
在上面的代码中,函数b就被包括在函数a内部,这时a内部的所有局部变量,对b都是可见的。但是反过来就不行,b内部的局部变量,对a就是不可见的。
这就是Javascript语言特有的“链式作用域”结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。
既然b可以读取a中的局部变量,那么只要把b作为返回值,我们不就可以在a外部读取它的内部变量了吗!
当函数a的内部函数b被函数a外的一个变量引用的时候,就创建了一个闭包。
函数嵌套函数,内部函数可以引用外部函数的参数和变量,参数和变量不会被垃圾回收机制所收回
三:闭包的好处
1.可以让一个变量长期驻扎在内存当中
2.避免全局变量的污染
3.私有成员的存在
应用:
1.模块化
------------------------------------------------------------------------------
var aaa = (function(){
var a = 1;
function bbb(){
a++;
alert(a);
}
function ccc(){
a++;
alert(a);
}
return {
b : bbb,
c : ccc
}
})();
//aaa.b(); //2
//aaa.c(); //3
//alert(a);
//alert(bbb);
alert(ccc);
-------------------------------------------------------------------------------------------------------------
2.累加
----------------------------------------------------------------------------------
function add(){
var bk = 10;
function b(){
bk++;
alert(bk);
}
return b;
}
var s = add();
s();//输出11
s();//输出12
s();//输出13
-------------------------------------------------------------------------------------------------------------
四:使用闭包需要注意的问题
1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便
改变父函数内部变量的值。
五、Javascript的垃圾回收机制
在Js中,如果一个对象不再被引用,那么这个对象就会被GC回收。如果两个对象互相引用,而不再被第3者所引用,那么这两个互相引用的对象也会被回收。因为函数a被b引用,b又被a外的c引用,这就是为什么函数a执行后不会被回收的原因。