JS中闭包的概念详解

1、概念

  1. 闭包就是函数高级应用
  2. 闭包即使不能完全理解也不会影响日常写代码,但是,如果能理解透彻,可以把代码写更好,主要的应用还是存在于一些面试考察

2、以往函数的使用过程

之前的函数使用:关注函数执行结果

  1. 定义阶段(函数声明)
    • 函数会在内存(等待执行的代码会放在内存中进行临时存储)中开辟一个"存储空间"
    • 函数内部的代码一模一样的放到这个"空间"
    • 再把存储空间地址函数名,方便在调用时使用到存在内存中的函数
  2. 调用阶段:直接使用函数名+调用运算 / 事件触发调用…等
    • 按照函数名的地址找到函数的存储空间
    • 形参赋值
      • 函数内部声明形参
      • 函数调用时实参给形参赋值
    • 预解析
      • 语法检查:语法有错误则后续代码不执行,无错误则正常解析代码
      • 声明提升:ES6后这个可以忽略,重点在语法检查,因为ES6后关键字变成了let
    • 存储空间中的函数代码拿出来进行执行
  3. 示例
 function foo( a , b , c ){
   let d = 10; // 1、给d赋值
   console.log(a + b + c ); // 2、执行加法计算 
                            // 3、执行console.log的调用
}
foo( 1,2,3 )

3、重新定义函数的使用

3.1、概念

重新定义函数的使用:关注函数执行结果机制/执行过程

  1. 解释
    • 之前会忽略函数调用时做的一些事,这里把忽略的事情讲清楚
  2. 定义阶段不变
  3. 调用阶段
    • 按照函数名的地址找到函数的存储空间
    • 形参赋值:和之前一样
      • 函数内部声明形参
      • 函数调用时实参给形参赋值
    • 预解析:和之前一样
      • 语法检查:语法有错误则后续代码不执行,无错误则正常去解析/解释代码
      • 声明提升:ES6后这个可以忽略,重点在语法检查,因为ES6后关键字变成了let
    • 在内存中开辟一个 "执行空间"
      • 函数定义阶段的存储空间相当于工厂里面的库房 => 只执行一件事:存储数据和在需要的时候取数据
      • 执行空间相当于车间 => 在车间中完成一些"装配工作",比如组合零件之类的,组合零件需要一个空间去完成这件事
      • 总结:执行空间不同于存储空间,存储空间单纯的就是存取行为,执行空间存在很多调用机制,为函数的执行创建一些机制
    • 将函数的"存储空间"中的代码拿出来:在刚刚开辟的"执行空间"中执行
    • 执行代码结束后,内存中开辟的 “执行空间” 会被立即销毁
  4. 示例:
// 调用阶段 => 这里的注释不加定义阶段和调用的1~3步
    function foo(){
       console.log("hello world"); // 2)当前代码会在"执行空间"中执行
                                   // 3)代码执行结束后,删除"执行空间"
    }
   foo(); // 1)调用时在内存中开辟了一块"执行空间" => 专门为foo做的

3.2、再聊"执行空间"

  1. 每个函数在声明的时候都会有一个"存储空间",但是每次调用都会生成一个"执行空间",即使是同一个函数,这个"执行空间"每次也都不一样
  2. "执行空间"会在函数执行后,进行销毁,但是"存储空间"不会,"存储空间"是在程序关闭(页面关闭)后进行统一销毁

3.3、学习"执行空间"的概念有什么意义?

  1. 意义:现在有一些技术手段,可以让这个"执行空间"不销毁 => 这个技术手段就是"闭包",利用"闭包"不执行空间销毁行为
  2. 解释:当认为当前的"执行空间"还会用时,就可以不销毁,闭包的技术其实就是函数内存里的执行空间不销毁
  3. 使用
    • 概念:正常情况下,函数的"执行空间"会在函数执行完毕后立即进行销毁,但是 => 一旦函数内部返回了一个引用数据类型,并且在函数外部有变量接收的情况下,那么这个执行空间就不销毁了
    • 解释:
      • 销毁其实也是根据一个机制去销毁的,JS的内存管理行为最开始是跟java学的,这个销毁行为是有一个机制的
      • 为什么要销毁:是因为有一个叫做垃圾回收机制的这样的一个垃圾判定工具/垃圾判定方式,来判定这个内存中的内容是不是垃圾,如果被内存回收极制判定为是垃圾了,那么它就会被销毁,如果判定为不是垃圾了,那就不销毁
      • 那现在做的事情其实就是闭包,我们"闭"的是:让计算机认为当前的这个数据它后面还会被使用,就不会被删除了
    • 如何删除"执行空间"数据
      • 如果想让内存把01空间判定为垃圾进行删除,则我们要给obj赋值一个null
      • 此时内存就会把这个01空间判定为垃圾,进行删除因为此时的obj虽然还是关联着01的,但是存储的不是一个"引用地址"而是一个空数据
  4. 示例
function foo(){
   let obj = { name : "hello world"}; 
   return obj;
}
 let res = foo(); 
// 解释1: 
     // 1、函数执行时,生成一个"执行空间",假设它的地址为"01",代码在这个"01执行空间"中执行 
     // 2、在"01执行空间"中定义了一个对象,假设对象的存储地址为"02"  
     // 3、在"01执行空间"执行代码的时候把"02"返回了 => 意味着它不仅仅在当前的函数作用域是有用处的,在外部也是有用的
     // 4、函数外部要接收一个地址:
          // 1)这个地址是在函数内部"01执行空间"中声明的 
          // 2)此时 02 和 01 产生了关联,也就意味着此时的01不是垃圾,不能被销毁 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值