在研究了挺长时间,终于明白了闭包是什么,以及怎么实现闭包。
但是还是很难真正理解它的作用,因为说起闭包,都知道是一个函数A内部有一个函数B,这个函数B访问了A中的私有变量。但是这样可以达到什么目的呢?
举一个缓存计算的例子:
const add = ()=>{
const cache = {};
return num=>{
if(num in cache){
console.log(`from cache ${cache[num]}`)
}else{
let calcRst = num + 10;
cache[num] = calcRst;
console.log(`calclated result is ${calcRst}`)
}
}
}
通过以上的例子,可以看出闭包有什么作用,
它可以让你不声明全局变量的情况下,以局部变量代替实现同样的功能。
至于网上其他的说法,比如,增加一个局部变量的生命周期,那是由于闭包的实现而导致的结果,不是目的。你的目的还是想要在离开函数的执行环境后使用这个变量,不想让这个变量在离开函数的执行环境就被回收了。但我们细想,如果没有闭包,我们怎么做?肯定是要把函数内部的这个变量提升到全局环境中去,所以最终的目的,我觉得目的只有一个,减少对全局环境的污染,使用局部变量来实现全局的功能。
使用闭包会有什么不好的地方?
因为闭包函数携带包含它的函数的作用域,就导致外部这个包裹函数内部的变量一直被别人引用,所以会影响这个外部函数的垃圾回收,从而导致使用闭包比普通函数更耗内存。
不过V8等优化后的JavaScript引擎会回收被闭包占用的内存。
再比如,我们实现一个迭代器的功能
function createIterator(items){
var i = 0;
return {
next:function(){
var done = (i >= items.length);
var value = !done ? items[i++] : undefined;
return{
done,
value
}
}
}
}
var iterator = createIterator([1,2,3]);
console.log(iterator.next()) //{done:false,value:1}
这里实现了一个构造迭代器的方法,next方法依赖i变量。当我们在全局环境中调用next方法时,i是一直会变的。如果不用闭包的话,只能在全局声明一个变量i了。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。