困惑了很久的闭包(closure)

一、什么是闭包

MDN

一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包closure)。也就是说,闭包让你可以在一个内层函数中访问到其外层函数的作用域。在 JavaScript 中,每当创建一个函数,闭包就会在函数创建的同时被创建出来。

    let a = "奥特曼"
    function fn() {
      console.log(a); //奥特曼
    }

通过MDN来看 你可以理解为上面就是一个闭包  下面三行概念是一个意思  

1.   函数 + 周围状态(环境的)的引用 = 闭包

2.「函数」和「函数内部能访问到的变量」(也叫环境)的总和,就是一个闭包。

3. 执行函数是f+a构成的结果就是闭包

通过这三个同样的概念 也是让我对闭包有了更新的概念   

在之前理解的是有权访问另一个作用域的函数叫闭包,当然这句话和上面三个理解其实也没什么太大区别,但是之前一直以为是函数嵌套形式

    function fn() {
      var a = "奥特曼"
      return function () {
        console.log(a)
      }
    }
    let a = fn()
    a()

误区①

上面是一个闭包确实没错,但是不能肯定只有嵌套这一种形式才叫做闭包,嵌套只不过是大部分情况,我同样可以不写return  不去接收调用接收fn函数的值,他只是没有被我调用,但他还是一个闭包结构。所以记住这一点,写return只是为了去接收它,并不影响他是闭包。同样我也可以把这个函数挂载到window下,同样可以访问到数据

    function fn() {
      var a = "奥特曼"
       function fn2() {
        console.log(a)
      }
      window.test=fn2
    }
    fn()  
    window.test()

误区②

扫描二维码关注公众号,回复: 15120923 查看本文章

调试工具的closure

不知道你们有没有这个疑惑,在之前学习都会发现闭包在断点调试的时候都会产生一个Closure 是不是调试一遍没有发现closure他就不是闭包了,其实也不能这么理解,就像十几年前的Chrome可能都不会出现Closure,当然出不出现我也不知道哈哈,而在断点调试什么时候出现Closure 是必须在函数调用或者return的时候才会出现

二、闭包的作用

封闭数据,提供操作

函数的运行机制是 调用=》销毁  在函数外部是调用不到的 而利用了闭包的技术可以在外部对变量进行操作

在JavaScript中 变量的作用域无非就全局变量域和局部变量,在使用变量的时候,函数内部可以访问函数外部的作用域变量,而函数外部访问不到函数内部的作用域变量

① 函数内部读取外部作用域变量(当然这也是闭包)

    let a = "奥特曼"
    function fn() {
      console.log(a); //奥特曼
    }
    fn() 

② 外部作用域读取函数内部变量

    function fn() {
      let a= "奥特曼"
    }
    console.log(a);  //a is not defined

如果说你不理解作用域 先去 看  全局作用域和局部作用域

通过上面代码来看 外部是拿不到函数内部的变量,这时候就用到了闭包

 闭包让你可以在一个内层函数中访问到其外层函数的作用域,来把这句话拆分成代码的形式就是子函数访问了父函数作用域的变量就形成了闭包 

    function fn() {
      var a = "奥特曼"
      function fn2() {
        console.log(a);
      }
      fn2()
    }
    fn()

看过上面的例子 我们再来看下一个特性

     function outerFn() {
      var i = 0;
      i++
      console.log(i);
    }
    outerFn() //1 
    outerFn() //1
    outerFn() //1

函数是在进行不断的创建销毁 创建销毁


    function outerFn() {
      var i = 0;

      function innerFn() {
        i++;
        console.log(i);
      }
      return innerFn;
    }
    var inner = outerFn(); 
    inner();  //1
    inner();  //2
    inner();  //3
    var inner2 = outerFn();
    inner2(); //4
    inner2(); //5
    inner2(); //6

特性

闭包可以让这些变量一直在内存中存在,不会随着函数的销毁而进行销毁

每次外部函数执行的时候,都会开辟一块内存空间,外部函数的地址不同,都会重新创建一个新的地址

关于内存泄漏:

内存泄漏指的是 再也访问不到的内存,依旧占着内存空间,我们就是用闭包去访问的数据并不是闭包造成了内存泄漏

关于为什么使用闭包:

你也可以利用闭包 读取函数内部作用域的变量

闭包无处不在!当你再用函数引入外部环境变量的时候,你已经用了闭包,只是你没有注意到!  这句话重点哦!!

猜你喜欢

转载自blog.csdn.net/m0_46846526/article/details/118157618#comments_26522669