《学习JavaScript闭包》链接:
http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html
最近想了解关于闭包的内容,查阅了许多文章,个人觉得阮一峰老师那篇《学习JavaScript闭包》最方便我本人理解。以下结合整理了一些主要内容,作为学习记录以及对知识点的整理。
JS变量作用域
js作用域分为全局变量和局部变量。
函数内部可以调用全局变量;
同时函数外部无法读取函数内部的局部变量。
注:函数内部需用var声明一个局部变量,否则生成的将是全局变量。
function f1(){
var i = 0; //这是局部变量
}
function f2(){
i = 0; //声明的是全局变量
}
函数外部如何调用局部变量?
在这之前需要了解js的链式作用域
链式作用域:子对象会一级一级的向上寻找所有父对象的变量,父对象的所有变量对子对象都是可见的,反之则不成立。
所以f2可以读取f1的局部变量,而f1不能读取f2的局部变量,利用这个特性,我们可以在f1函数内部再定义一个f2函数,用来返回f1的值。
例子:
function f1(){
var i = 0;
function f2(){
alert(i);
}
return f2;
}
var result = f1() //此时的result就是f2
result(); //结果是0,成功获取了f1中的局部变量
闭包的概念
闭包就是上面的f2函数
所以可以把闭包理解成定义在一个函数内部的函数。
闭包的用途
1.可以读取其他函数内部变量;
2.可以使变量的值始终保存在内存中。
下面放一段代码进行说明
function f1(){
var i = 0;
add = function(){ //全局变量定义函数
i++;
}
function f2(){
alert(i);
}
return f2;
}
var result = f1(); //此时的result是f2()
result(); //显示结果为0
add(); //调用add函数
result(); //显示结果为1
在这里f2就是闭包,也就是说result也是闭包,两次打印结果分别为0
和1,说明f1的局部变量一直存在于内存中,没有被垃圾回收机制回收。
javascript垃圾回收机制原理:解决内存的泄露,垃圾回收机制会定期(周期性)找出那些不再用到的内存(变量),然后释放其内存。
产生这种情况的原因:f1是f2的父函数,f2被赋给了全局变量result,而f2的存在又依赖于f1,所以f1会一直存在于内存中。
使用闭包需要注意的事项
1.闭包会使函数中的变量都保存在内存中,所以不能滥用闭包,否则
网页性能会出现问题。
2.闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把
父函数当作对象(object)使用,把闭包当作它的公用方法(Public
Method),把内部变量当作它的私有属性(private value),这时
一定要小心,不要随便改变父函数内部变量的值。