JS中的闭包
什么是闭包?
我们都知道,js的作用域分两种,全局和局部,基于我们所熟悉的作用域链相关知识,我们知道在js作用域环境中访问变量的权利是由内向外的,内部作用域可以获得当前作用域下的变量并且可以获得当前包含当前作用域的外层作用域下的变量,而外层作用域下无法获取内层作用域下的变量,同样在不同的函数作用域中也是不能相互访问彼此变量的,那么我们想在一个函数内部也有限权访问另一个函数内部的变量该怎么办呢?闭包就是用来解决这一需求的,我理解闭包的本质就是在一个函数内部创建另一个函数。从而达到能够读取其他函数内部变量的函数的目的。
例:
function a(){
var num = 5;
function b(){
console.log(num);//函数b中的变量num会读取到函数a中的变量num的定义
}
return b;//此时的函数b就是一个闭包函数因为他能够访问到outer函数的作用域
}
var c = a(); //此时c是a内部return的b函数体,外部函数a已运行完毕,但是变量num仍被内部函数引用,故不会释放。
c(); //打印结果是5
闭包有三个特点:
1.函数嵌套函数
2.内部的函数可以引用外部函数的参数或者变量
3.参数和变量不会被垃圾回收机制回收,因为内部函数还在引用
使用闭包的好处
1.变量可以长期驻扎在内存之中
2.避免全局变量的污染,有私有成员
例:
1.普通函数的调用
function a(){
var num = 1;
num++;
console.log(num);
}
a(); //打印2
a(); //还是打印2,因为函数a执行完毕,根据垃圾回收就回收了其中num变量,再次执行,重新赋值计算时,此时的num变量又回到了1
2.使用闭包的方式调用
function a(){
var num = 1;
return function(){
num++;
console.log(num);
}
}
var b = a();
c(); //打印2
c(); //打印3,因为函数a执行过后,因为其内部的匿名函数还在引用变量num,所以不会被回收,故而会在已经计算过一次的基础上再计算一次,在上一次执行后变量num的值上进行递增
同时也可以用函数表达式来改写
例:
var a = (function(){
var num = 1;
return function(){
num++;
console.log(num);
}
})() //函数表达式自执行,结果是内部函数体
a(); //同上
a(); //同上
使用闭包时需要注意的问题
引用的私有变量不能被销毁,增大了内存消耗,所以要慎用,以防止产生内存泄漏。解决方法可以在使用完变量后手动为它赋值为null。