闭包的理解

156 阅读3分钟

一、什么是闭包?

  • 官方解释:MDN中对闭包 理解:闭包是一个函数以及其捆绑的周边环境状态(lexical environment词法环境)的引用的组合。换而言之,闭包让开发者可以从内部函数访问外部函数的作用域。
  • 初略理解:闭包就是能够读取其他函数内部变量的函数。(阮一峰闭包理解 )

二、闭包是怎么样产生的?

  1. 函数嵌套
  2. 内部函数引用外部函数的局部变量
function fn1() {
    var a = 2
    function fn2(){
        console.log(a);
    }
    fn2()
}
fn1() //2 
-- 函数fn1嵌套fn2 --
-- 函数fn2调用的时候,在作用域内寻找变量a,但是当前无变量a,便向上寻找到了,fn1作用域内的a变量 --

三、在浏览器内调试查看

由上可知,在我们调用fn2的时候

image-20230130214044131.png

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,那么他不会被垃圾回收机制回收)

五、闭包变量存储的位置

直接说明:闭包中的变量存储的位置是堆内存。

假如闭包中的变量存储在栈内存中,那么栈的回收 会把处于栈顶的变量自动回收。所以闭包中的变量如果处于栈中那么变量被销毁后,闭包中的变量就没有了。所以闭包引用的变量是出于堆内存中的。

六、闭包的用途

  1. 可以读取函数内部的变量
  2. 让变量的值始终保持在内存中。

七、使用闭包需要注意什么

  1. 由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在 IE 中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
  2. 闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。