闭包

作者: 未路过 | 来源:发表于2022-08-25 22:28 被阅读0次

从广义的角度来说:JavaScript中的函数都是闭包;
从狭义的角度来说:JavaScript中一个函数,如果访问了外层作用域的变量,那么它是一个闭包; 闭包由两部分组成:函数+可以访问的自由变量 按道理说,foo执行完之后,它的ao对象应该也就销毁了,但是因为闭包,它没有被销毁

1.普通函数执行

var message = 'hello';
function foo(){
  var name = 'foo';
  var age = 18;
}

function test(){
  console.log('test');
}

foo();
test();

1.在执行所有代码之前,引擎会在内存里创建GO对象(ox100),它里面有String对象啦,window对象这些 对象。是被提前创建好的。然后现在去执行代码, GO对象是不会被销毁的
2.创建执行上下文栈
3.然后执行全局代码,创建全局执行上下文,然后创建全局执行上下文的VO,这个Vo指向GO。
4.然后,这个时候解析全局代码,往全局GO里面加东西了,原来的全局里面有Date,window,String等等,加入
message(undefined)foo(oxa00),test(oxboo)等变量。解析foo是函数,就创建一个函数对象 foo(oxa00),里面有函数的父级作用域,也就是全局的GO对象(ox100)。,还有函数执行体(函数代 码)。 解析test是函数,就创建一个函数对象test(oxb00),里面有函数的父级作用域,也就是全局的GO对象 (ox100)。,还有函数执行体(函数代码)

24.PNG

5 接下来执行执行代码,先给message赋值,变成了hello,然后执行函数foo。

6 创建foo函数的函数执行上下文。往里面创建VO对象,VO指向AO对象。创建一个foo函数的AO对象(ox200)。

默认里面没有对象,然后解析函数,里面放入name:undefined,age:undefined

image.png

7.然后执行一行一行执行foo里面的代码,同时把AO里面的name赋值'foo',age赋值18;


image.png

8.foo函数执行完之后,栈里面的foo函数执行上下文就会被销毁,一旦销毁,对foo的AO对象的引用将会没有,然后oxaoo就会被销毁。

image.png

一般情况下,在函数执行上下文被销毁的同时,函数的AO对象也会被销毁

9.test函数执行完之后也是一样,test的AO对象也会被销毁。代码执行完之后的内存结果就是上图。

2.闭包函数执行

var message = 'hello'
function foo(){
  var name = 'foo';
  var age = 18;

  function bar(){
    console.log(name);
    console.log(age);
  }

  return bar
}


var fn = foo();
fn()

执行完var fn = foo();之后

image.png

然后foo的执行上下文被销毁,但是bar不会被销毁,因为fn指着它。 然后bar对象不会被销毁,它上面的foo的ao对象也不会被销毁的。因为bar里面有parentScope这个东西,它指向foo的AO对象。


image.png

接下来执行fn()


image.png

然后销毁fn的执行上下文.


image.png

foo的AO对象是没有被销毁的,因为bar的父级作用域是指向foo的AO的。 内存泄漏:这里的bar函数对象一直不会被销毁,也就是foo的AO也一直不会被销毁。 如果执行完一次fn之后,就再也不会执行这个fn了,那么保存的bar和foo的AO也就没有意义了。 该销毁的东西没有被销毁,就是内存泄漏。 fn= null;就可以解决


image.png

虽然这时候bar和foo的AO循环引用,但是根据标记清除法,只要从根对象OG开始能找到的对象就不会被销毁。

但是bar和foo的AO从根对象指不向他们,他们就会被销毁。


image.png

如果也想销毁掉foo这个函数,也是一样,直接foo = null;就可以了;

image.png

3. 内存泄漏

image.png image.png

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
</body>
<script>
  // var arr = new Array(1024 * 1024).fill(1)
  // console.log(arr);
   //整数占据四个字节 4Byte  1MB=1024KB
   //1024*1024*4 = 1024 * 1Kb * 4B = 4kB * 1024 = 4MB
   //现在这个数组占据的空间是4MB

   function createFnArray(){
    var arr = new Array(1024 * 1024).fill(1);

    return function(){
      console.log(arr.length);
    }
   }
   var arrayFns = [];

   for(var i = 0; i < 100; i++){
    
    //调用100次createFnArray(),就会有100个createFnArray对应的AO。
    //返回100个函数对象,每一个函数对象都会引用createFnArray对应的AO。
    arrayFns.push(createFnArray());
   }
</script>
</html>

4.闭包中没有被使用的属性

   function foo(){
     var name = 'why';
     var age = 18;

    function bar(){
        debugger
      console.log(name);
    }
    return bar
   }

   var fn = foo();
   fn();

foo的AO对象不会被销毁,里面有name和age两个变量,name因为被bar引用,不会被销毁,但是从引擎优化的角度,发现这里age根本不会被用到,依然保留age的话,会占用内存空间,影响内存性能。一般情况下,js引擎会把多余的属性销毁掉。

5.对象中的函数

var test = "test"
 var p1 = {
   p1eating(){
    // console.log(test);
    var p1test = "p1test"
     var p2 = {
       p2eating(){
         var p2test = "p2test"
         var p3 = {
           p3eating(){
             //console.log(test);
             console.log(p1test);
             //console.log(p2test);
           }
           
         }
         p3.p3eating()
       }
     }
     p2.p2eating()
   }
   
 }

 p1.p1eating()

对象中的函数也是存在闭包的,方法中的变量也是向上层作用域中去找的,而且对象不是一个作用域,对象中的方法和全局才是

相关文章

  • swift-闭包

    闭包 闭包定义 闭包简化 - 尾随闭包 闭包参数 闭包返回值 闭包的循环引用

  • 闭包,闭包,闭包

    1、这家伙到底是什么? 网上关于这个的讨论的太多了太多了,有各种的举例子,但是大部分还在寻找这个答案的小伙伴对于变...

  • 闭包-Closures [swift 5.1]

    闭包的语法 尾随闭包 闭包逃离 自动闭包

  • Day7 闭包(Closures)

    本页包含内容:• 闭包表达式• 尾随闭包• 值捕获• 闭包是引用类型• 逃逸闭包• 自动闭包 1、闭包表达式 闭包...

  • Python闭包

    闭包 = 环境变量 + 函数 调用闭包内部的环境变量 闭包的经典误区 闭包与非闭包实现人类走路 非闭包 闭包

  • 闭包(closure)

    ● 闭包基础 ● 闭包作用 ● 闭包经典例子 ● 闭包应用 ● 闭包缺点 ● 参考资料 1、闭包基础 作用域和作...

  • swift- 闭包一

    /*• 闭包表达式• 尾随闭包• 值捕获• 闭包是引用类型• 逃逸闭包• 自动闭包*/

  • (9) python之闭包

    闭包闭包 = 函数 + 环境变量(函数定义的时候) 一个最简单的闭包 闭包不受外部变量影响 非闭包 闭包 闭包 只...

  • Swift-进阶 :闭包(二)逃逸闭包 & 非逃逸闭包

    本文主要分析逃逸闭包 、非逃逸闭包、自动闭包 逃逸闭包 & 非逃逸闭包 逃逸闭包定义 当闭包作为一个实际参数传递给...

  • javascript闭包详解

    跟我念 bi 闭 bao包 ,闭包的闭,闭包的包。。 闭包的简介 在计算机科学中,闭包(英语:Closure),又...

网友评论

      本文标题:闭包

      本文链接:https://www.haomeiwen.com/subject/szizgrtx.html