javascript的作用域分两种:全局和局部,基于我们所学的作用域及预编译相关知识,js作用域环境中访问变了的权利是由内到外的内部作用域可以获得父级作用域的变量和参数,反之则不能。也就是说外层作用域无法获取内层作用域下的变量和参数,同样在不同的函数作用域中也是不能相互访问到彼此的变量和参数的
那么想在函数内部想访问另一个函数内部的变量和参数就得用到闭包来解决这一需求。
闭包的本质就是在一个函数内部创建另一个函数!!!
在函数外面是无法读取到函数内的局部变量
函数内部声明变量时一定要加var,否则就声明了一个全局变量。
闭包有三个特性:
1.函数嵌套函数;
2.函数内部可以引用函数外部的参数和变量;
3.参数和变量不会被垃圾回收机制回收掉;
例子如下:
这段代码中fun函数嵌套了一个fun2函数,return fun2 这一步把内层函数fun2返回给fun
也就等于 fun = functon fun2(){a++;console.log(a);} 然后在又把fun赋值给了num 又执行了num()
此时执行的是fun2 函数fun2里并没有a这个变量 但是他的父级函数里有 所以他可以获取fun函数里的
变量a的值
num(); //112
一般情况下,函数fn执行完后,就应该它本身与它里面的参数和变量一同被销毁,但在这个例子中,匿名函数作为fn的返回值被赋值给了fn1,相当于fn1=function(){var n = 0......},并且匿名函数里引用着外层函数变量num,所以变量num无法被销毁,而变量n是每次被调用时新创建的,所以每次fn1执行完后他把属于自己的变量连同自己一起销毁,最后就剩下num,就产生了内存消耗的问题
fn1(); //1 6
fn1(); //1 7
fn1(); //1 8
闭包的用途:
它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中,不会在f1调用后被自动清除。
闭包的优缺点:
优点:
1.保护函数内的变量安全,保护变量不被污染;
2.一个变量长期储存在内存中;
3.实现封装,防止变量跑到外层作用域中,发生命名冲突;
4..匿名自执行函数,匿名自执行函数可以减小内存消耗;
缺点:
1.内存不会被释放,增加内存使用量;