一、什么是闭包?
- 官方解释:MDN中对闭包 理解:闭包是一个函数以及其捆绑的周边环境状态(lexical environment,词法环境)的引用的组合。换而言之,闭包让开发者可以从内部函数访问外部函数的作用域。
- 初略理解:闭包就是能够读取其他函数内部变量的函数。(阮一峰闭包理解 )
二、闭包是怎么样产生的?
- 函数嵌套
- 内部函数引用外部函数的局部变量
function fn1() {
var a = 2
function fn2(){
console.log(a);
}
fn2()
}
fn1() //2
-- 函数fn1嵌套fn2 --
-- 函数fn2调用的时候,在作用域内寻找变量a,但是当前无变量a,便向上寻找到了,fn1作用域内的a变量 --
三、在浏览器内调试查看
由上可知,在我们调用fn2的时候
scope是当前的作用域环境,里面有个Closure的属性便是闭包。
四、再举例理解闭包
function add() {
var count = 0;//函数全局作用域 标记为flag2
return function () {
count += 1;//函数的内部作用域
console.log(count);
}
}
var s = add()
s();//输出1
s();//输出2出1
: 我们来理解这个函数的执行
- 每次执行s(),其实都是执行
function () {
count += 1;//函数的内部作用域
console.log(count);
}
这个函数
- 第一次执行 s(),执行函数 count += 1,所使用的 count 应该是 0
- 第二次执行 s() 的时候其实是继续执行 add 的返回函数,还是 count+=1; 然后再输出 count ,这里问题就来了,不应该继续向上寻找,找到 count=0;然后输出 1 吗? 也就是说 add (),只被执行了一次。然后执行两次 s (),那 count 的值就是只声明了一次。
- 下面执行的都是 s (),那第二次的 count 的值是从哪儿来的,没错它还是第一次执行 add 时,留下来的那个变量。
- 涉及到一个垃圾回收机制 ( 如果一个变量的引用不为0,那么他不会被垃圾回收机制回收)
五、闭包变量存储的位置
直接说明:闭包中的变量存储的位置是堆内存。
假如闭包中的变量存储在栈内存中,那么栈的回收 会把处于栈顶的变量自动回收。所以闭包中的变量如果处于栈中那么变量被销毁后,闭包中的变量就没有了。所以闭包引用的变量是出于堆内存中的。
六、闭包的用途
- 可以读取函数内部的变量
- 让变量的值始终保持在内存中。
七、使用闭包需要注意什么
- 由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在 IE 中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
- 闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。