在阅读vue源码时发现vue源码大量运用了闭包的技巧来实现某些特性,发现自己并不是真的理解闭包,所以写这篇文章来深入学习闭包。
闭包的概念
************
可能我们在书写js代码时,不知不觉中已经使用了闭包。我们从下边这段代码具体来看一下:
javascript
function foo() {
var a = 2;
function bar() {
console.log(a);
}
return bar;
}
var baz = foo();
baz(); // 2——朋友,这就是闭包的效果。
这段代码中,函数foo(),内部有一个局部变量a以及一个函数bar(),并且返回了函数bar。
在foo执行后,通常会觉得foo内部的作用域已经销毁,它内部的a变量应该不复存在。但由于闭包的性质,函数bar()内部引用foo的内部作用域,而这个引用就叫做闭包。
闭包的用处
闭包给JavaScript代码带来了很多的灵活性,它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。
来看下边这段代码:
javascript
//函数add返回了一个内部函数,这个内部函数持有add的参数的引用。
function add(a){
return (b)=> b+a
}
const add5 = add(5) // add5通过闭包的性质可以引用add的局部变量a。
add5(1) //6
理解闭包
要理解闭包,需要理解作用域链。还是以上文中的代码为例:
内部函数的作用域链中持有add函数的活动对象,所以在add函数执行完返回内部函数后,add函数的活动对象a仍然不会被销毁,直到持有内部函数的引用的对象全部被销毁后。
使用闭包的注意点
由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。