变量的作用域
理解闭包,需要先理解js的变量作用域,即全局变量和局部变量,函数内部可以直接读取全局变量,函数外部则不能读取函数内部的局部变量。
函数的局部变量是在函数作用域内进行工作的,为了使用函数内部的局部变量,那么可以在函数内部定义一个内部函数,这个内部函数天然可以读取外层函数的局部变量。
function bar(){
var name = 'a';
function foo(){
console.log(name);
}
}
这里就涉及到了js特有的链式作用域,函数foo会一层一层的向外查找所有父级对象的元素,反之则不行,既然函数foo能使用函数bar的局部变量,那么,我们把foo函数return出去,那么就可以在函数外部使用函数内部的局部变量!
function bar(){
var name = 'a';
function foo(){
console.log(name);
}
return foo()
}
var fc = bar();
fc(); //'a'
这里其实就是闭包。
闭包
「函数」和「函数内部能访问到的变量」的总和,就是一个闭包,简单的说也就是一个能够读取到一个函数的局部变量的函数和读取的这个局部变量共同构成闭包。
从结构上来讲,闭包就是父级函数内部定义一个子函数,该子函数可以读取到父级函数的所有局部变量,构成闭包,子函数是否被return出去和闭包没有关系,return出去只是为了能够正常的使用闭包。
闭包的作用
私有化变量,处于闭包中的局部变量,除了被return出去的函数,没有别的途径对其进行访问。
这里又出现了新的问题,由于js的垃圾回收机制,会对使用完成或者没有使用的局部变量进行回收,但是在闭包过程中,局部变量一直被return出去的函数调用,导致变量始终会储存在内存中。
闭包使用过程中存在的问题
谨慎使用闭包,由于闭包的特殊性,会大量的占用内存。解决方法是,在退出函数之前,将不再使用的局部变量全部删除,或者将使用完成的函数赋值为null,手动清除内存。