JS闭包
Posted daijinjia
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JS闭包相关的知识,希望对你有一定的参考价值。
一、闭包是js里面一个很强大东西,那么什么是闭包呢?我们看看下面这个例子:
function funA(){
var a=5;
return function(){
alert(a);
}
}
var test = funA();
test();//5
这里就是在函数funA里面又返回了一个函数,这种情况就是一种闭包。更加书面化的描述就是A函数中嵌套着B函数,B程序中有用到A的变量,当外部函数C调用函数A时,虽然A已经执行完毕,理论上函数执行完毕,它就要被弹出栈,但是由于B要用到A,所以A的变量被保存到内存中不被销毁,我们称函数B是闭包。
当时我在闭包的时候,有个困惑的地方。就是如果我函数里有函数,但是这个函数没有使用外面函数的变量那还算是闭包吗?经过我的查阅看到了如下的几种闭包的定义:
①闭包是指有权访问另一个函数作用域中的变量的函数(javascript高级程序设计)
②闭包的本质就是在一个函数内部创建另一个函数
③函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起构成闭包(closure)。也就是说,闭包可以让你从内部函数访问外部函数作用域。在 JavaScript 中,每当函数被创建,就会在函数生成时生成闭包。
④内部函数总是可以访问其所在的外部函数中声明的参数和变量,即使在其外部函数被返回(寿命终结)了之后。
通过这些还是很难得出结论,然后通过询问后,发现其实无论内部函数是否使用了外部函数的变量这都算是闭包,因为即使我们没有使用,内部的函数也是有权访问外部函数的作用域的,所以闭包就是函数内创建另一个函数。
二、知道了什么是闭包,那么接下来我们就应该要知道为什么要使用闭包。
首先我们要知道js的变量作用域分为全局和局部。在js中内部可以访问外部;当前作用域能访问上层的变量和函数;子对象可以一步步向上访问所有父对象的变量,反之则不行。那么如果我们想要函数外部使用函数内部的变量改怎么办呢?这就是使用闭包的原因之一,就是要实现一些不符合作用域规则的操作。
以下是闭包的一些用途:
- 读取函数内部的变量。
- 让这些变量的值始终保持在内存中,不会在调用函数后被自动清除。
- 方便调用上下文的局部变量,利于代码封装。
- 模拟私有变量。
闭包的一些运用具体实例:
- setTimeout(闭包实现传参)
- 回调
- 封装变量
- 为节点循环绑定click事件
三、闭包的优缺点以及具体问题实例
优点:
1.保护函数内的变量安全 ,实现封装,防止变量流入其他环境发生命名冲突
2.在内存中维持一个变量,可以做缓存(但使用多了同时也是一项缺点,消耗内存)
3.匿名自执行函数可以减少内存消耗
缺点以及解决思路:
1.其中一点在上面的内容里已经有体现了,就是被引用的私有变量不能被销毁,增大了内存消耗,造成内存泄漏,解决方法是可以在使用完变量后手动为它赋值为null;
2.其次由于闭包涉及跨域访问,所以会导致性能损失,我们可以通过把跨作用域变量存储在局部变量中,然后直接访问局部变量,来减轻对执行速度的影响。
闭包的具体问题实例,我看了很多博客大多数都讲了三种实例,第一种是变量变化的问题,第二种是this问题,最后一种是内存泄漏问题。前两种的话很多人包括我自己觉得这不是闭包的问题而是涉及到了js其他知识,归根结底不是闭包所产生的问题,那么内存泄漏这真的就是闭包所产生的问题。这算是闭包产生的一个很大的问题吧,具体的原因就是因为一般函数在执行完后都会被释放回收,但是使用了闭包后,在函数执行结束后并不会释放,因为函数内部的函数还要使用外部函数的作用域,如果释放了就会发生错误,这种不释放就造成了内存的泄漏,解决的方法也很简单,就是你使用完之后就要去主动的释放,这样就可以很有效的解决内存泄漏的问题了。
以下是我阅读的一些参考资料:
javascript高级程序设计(第三版)
https://www.cnblogs.com/Renyi...
https://www.cnblogs.com/itjef...
https://www.jianshu.com/p/26c...
https://developer.mozilla.org...
https://blog.csdn.net/weixin_...
https://blog.csdn.net/qq_2113...
https://blog.csdn.net/u010283...(js链试作用域)
http://es6.ruanyifeng.com/(ES6入门教程)
https://blog.csdn.net/nfer_zh...(let和var的区别)
以上是关于JS闭包的主要内容,如果未能解决你的问题,请参考以下文章