学习前端的过程中,特别是在Javascript学习的过程中,每个学习者都会遇到一个很难理解的难点,那就是闭包。下来我来讲讲我对闭包的了解:
函数作用域
首先,讲闭包,就一定要讲到JS的作用域(函数作用域)了,函数作用域有一些特点;
特点一(函数能访问到函数外部的变量)
var num =10;
function fn1(){
console.log(num);
}
fn1(); //10
特点二(函数内部线的变量不能被函数外部访问)
function fn2(){
var num =10;
}
console.log(num);//结果为undefined;
如何在函数外部访问函数内部的变量呢,正常情况下,是访问不到的。因此我们要通过一种变通的方法,就是在函数内部定义一个函数,这个函数就可以帮我访问外层函数的变量。
来个最简单的闭包看看
function fn1(){
var a=1 ;
function fn2(){//这里就产生了闭包。。。(@_@)
console.log(a);//不信就打开Chrome浏览器在var a =1;这一行打个断点
//你会看到
}
}
fn1();
如下图所示:
简单来说闭包就是在嵌套函数中有访问外层函数成员变量权限的函数(一般人的理解)。。而我理解中的闭包是什么呢?
我认为闭包就是内部函数对外部函数的引用
闭包的作用
使用闭包有两个好处:一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。
function foo(){
var a = 1;
function fo(){
a++;
console.log(a);
}
return fo;
}
var f = foo();
f();//2
f();//3;从这里我们可以看到当输出2的时候,变量a并没有被释放,而是被保存在内存中 所以在输出3之前,a=2;
但是闭包有一个很大的缺点:就滥用闭包会造成内存泄漏;
内存溢出和内存泄漏
内存溢出是一种程序运行时出现的错误,也就是说当程序运行需要的内存超过了剩余的内存,就会抛出内存溢出的错误。
而内存泄漏是占用的内存没有及时释放,内存泄漏积累多了容易导致内存溢出:因为被占用的内存没有被释放,可用的内存越来越少了,程序需要的内存超过了可用的内存。
常见的内存泄漏:意外的全局变量,没有及时清理的计时器或回调函数,闭包等;
就上面的例子而言,假如你运行了多次f();就会造成内存泄漏,因为闭包的存在,变量a没有成垃圾变量被垃圾回收机制回收,所以就会一直存在内存中,a=2,a=3…….a=n。所以为了防止出现内存泄漏,我们在闭包运行完成后,要把闭包处理成垃圾函数,使得垃圾回收机制进行回收。我们可以f()之后,把null赋给f;这样就等于把闭包给处理成了垃圾函数了。
