一、理解闭包前js基础
1、作用域链(作用域、作用域链中有说)。
2、js的内存回收机制。一个函数在执行开始的时候,会给其中定义的变量划分内存空间保存,以备后面的语句所用,等到函数执行完毕返回了,这些变量就被认为是无用的了,对应的空间也就被回收了。下次再执行此函数的时候,所有的变量又回到最初的状态,重新赋值使用。
但是如果这个函数内部又嵌套了另一个函数,而这个函数可以被外部被调用到的,并且这个内部函数又使用了它外部函数的某些变量的话,这种内存回收机制就会出现问题(如果在外部函数返回后,又直接调用了内部函数,那么内部函数就无法读取到他所需要的外部函数中变量的值了)。所以js解释器在遇到函数定义的时候会自动把函数和他可能使用的变量(包括本地变量和父级和祖先级函数的变量(自由变量))一起保存起来。也就是构建一个闭包,这些变量将不会被内存回收器所回收,只有当内部的函数不可能被调用以后(例如被删除了,或者没有了指针),才会销毁这个闭包,而没有任何一个闭包引用的变量才会被下一次内存回收启动时所回收。
二、问题引入
需要创建一个计数器,同意计算数值,且可在所有函数用使用。
首先想到方法:引用全局变量,创建函数设置计数器递增。
var a = 0;
function add(){
a++;
}
add();
console.log(a); //1
此种方法问题:设了计数器为全局变量,则其他任何地方都可以直接改变a的值,不止add函数;全局变量容易被重新定义覆盖。
三、使用闭包
function outerFunc(){
var a=0; //定义计数器
function innerFunc(){
//内嵌函数,根据内存回收机制,outerFunc执行后a变量不会随父方法销毁而被回收,还是被innerFunc引用着
return a+=1; //根据作用域链,此函数可以访问上层作用域的变量a
}
return innerFunc; //返回内部函数
}
var add = outerFunc(); //内部函数赋值给add变量
console.log(add()); //1
由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”。
四、闭包作用
1、读取使用函数内部作用域里的变量。
2、私有变量,避免全局污染。
3、变量会长期存在于内存中。(也是缺点)
网友评论