1.什么是闭包
要理解什么是闭包,就得先理解变量的作用域。
在JavaScript中,有两种作用域,全局作用域和函数作用域。
var a=1;
function fn(){
var b =2;
console.log(a)
}
fn.call() // 3
console.log(b) //Uncaught ReferenceError: n is not defined
上面代码中,函数fn可以读取全局变量a,但是函数外部无法读取函数内部声明的变量b。这就是全局作用域和函数作用域。
function fn1(){
var a =1;
function fn2(){
console.log(a)
}
return fn2;
}
闭包的官方解释为,闭包是函数和声明该函数的词法环境的组合。
说的比较生僻难懂。通俗些说就是,如果一个函数使用了函数作用域范围外的变量,那么这个函数和这变量就可以称为一个闭包。
上面例子中,函数fn2和变量a就可以称为一个闭包。
2.闭包的用途
闭包的用途主要三个,读取函数内部的变量、让变量始终保留在内存中、封装对象的私有属性和私有方法。
2.1.读取函数内部变量
function fn1(){
var a =1;
function fn2(){
console.log(a)
}
return fn2;
}
var number =fn1(); // 输出为1,即可获取到函数fn1内的变量a。
上述代码中,函数fn1返回值为fn2,fn2可以获取到fn1的函数内变量,所以就可以函数f1的内部变量了。
2.2.让变量始终保留在内存中
function fn(x){
return function(){
return x++;
}
}
var number= fn(1);
number.call(); //1
number.call(); //2
number.call(); //3a
2.3.封装对象的私有属性和私有方法
function fn(x){
return function(){
return x++
}
}
var a =fn(1);
a(); //1
a(); //2
var b =fn(5);
b(); //5
b(); //6
var c =fn(10);
c(); //10
c(); //11
上述代码中,外层函数fn每次运行,都会生成一个新的闭包,而这个闭包又会保留外层函数的内部变量。
a、b、c 是相互独立的,函数fn的内部变量参数x,通过闭包,变成了a、b、c各自的私有变量参数。
3.闭包的缺点
闭包会使函数中的变量都被保存在内存中,内存占据很大,使用闭包时应格外注意内存消耗大,否则会造成网页的性能问题。