闭包是js中的一大特色,也是一大难点。简单来说,所谓闭包就是说,能够读取其他函数内部变量的函数。所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。
闭包的三大特点为:
1、函数嵌套函数.
2、内部函数可以访问外部函数的变量.
3、参数和变量不会被回收.
举例来说:
var n = 999;
function fn1(){
console.log(n);
}
fn1(); //999
另一方面,在函数外部自然无法读取函数内的局部变量。
function fn1(){
n = 999;
}
fn1();
console.log(n); // 999
这里有一个地方需要注意,函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量。
function fn(){
var n = 10;
return function(){
console.log(n);
}
}
var fun = fn();
fun(); //10
这个例子中,变量n在fn方法外部是无法访问的,但fn方法里面,嵌套了一个匿名函数,通过return返回,fn作用域中的变量n,可以在匿名函数中访问。并且当fn方法执行后,变量n所占内存并不会释放,以达到嵌套的函数还可以访问的目的。闭包的作用在于,可以通过闭包,设计私有变量及方法。
二、如何从外部读取局部变量?
出于种种原因,我们有时候需要得到函数内的局部变量。但是,前面已经说过了,正常情况下,这是办不到的,只有通过变通方法才能实现。
那就是在函数的内部,再定义一个函数。
function fn1(){
n = 999;
function fn2(){
console.log(n); //999
}
}
在上面的代码中,函数fn2就被包括在函数fn1内部,这时f1内部的所有局部变量,对fn2都是可见的。但是反过来就不行,fn2内部的局部变量对fn1就是不可见的。这就是javascript语言特有的‘链式作用域’结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。
总结:1、闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量。闭包的缺点就是常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。
2、不必纠结到底怎样才算闭包,其实你写的每一个函数都算作闭包,即使是全局函数,你访问函数外部的全局变量时,就是闭包的体现。