模块化

515 阅读3分钟

重点关键:

commonJS 引入导出的都是一个对象

  • 同步还是异步:同步
  • 执行顺序,即如何解决循环引用的问题?只执行已经输出的部分 跳过去就不跳回来了
  • 是值还是引用拷贝?值拷贝
  • require缓存:只有第一次require调用,后面require直接从缓存中的结果中取

ES module

  • 同步还是异步:异步 (浏览器需要异步,不然全都阻塞卡顿了)
  • 执行顺序:入口文件组织依赖图,依赖图上的每个节点存的是引用地址 ,循环引用的会打一个正在解析中的tag,解析完了通知我一下 我直接更新,执行好了后面的给他一个信号
  • 是值还是引用拷贝?引用拷贝
  • 缓存

什么是模块

是一种提供对外通信接口,进行代码区分分割的管理方式

为什么要模块化

  1. 关注分离:分解复杂问题成多个子问题;
  2. 适合多人、大型软件开发:内聚(变量,行为内聚在模块内,对外暴露接口进行通行);方便复用、管理;

发展史

函数时代→命名空间→利用闭包→现代模块化机制(CommonJS/ESM)

  • 命名空间

通过给对象起名来隔离,起名很麻烦,空间开销大

  • 利用闭包

问题一:闭包里的东西到底存在内存结构中的哪里?

函数里面存的变量是放在栈里面,函数执行完栈内存就会释放 ,栈空间有限但是可以快速吸收释放,因为函数特性来说是立即执行的,也是应用中存在最多的,一直在执行-释放-执行-释放,所以函数里的变量肯定会选择栈来存放 。

闭包是可以一直持有对里面变量的访问,所以闭包里的东西到底存在内存结构中的哪里? 堆 内存一直存在,才能被访问。

逃逸分析:浏览器底层引擎提供的一个功能 (浏览器帮我分析哪些变量我还会用,哪些不会用到)和闭包有什么关系? 闭包的核心,通过浏览器底层原理实现的

  • CommonJS

commonJS执行顺序:同步执行,会执行前面已经输出的部分

exports暴露的时候,挂在一个对象上,别人可以通过对象去拿。

require引入的时候,require会有一个缓存,只有执行一次,然后把结果缓存起来,下次一require的时候直接从缓存里面取

★问题:commonJS怎么解决同步执行中的循环引用的问题

首先明确 :commonJS是值拷贝还是引用拷贝? 值拷贝

循环引用: A引入B模块输出B的内容, B模块引入输出A的内容

a中的require a文件,a文件中已经跳到去执行b了,所以首页的这个const b其实拿的是缓存里的结果,并不会再执行一遍b.js

如果跳过去的时候没有值,没执行 那结果就是一个空对象

  • ESM

ESM是值拷贝还是引用拷贝 ?异步交替执行,引用拷贝

举例:同上 入口index请求a和b模块,其中a.js中import了b,b中import了a。

就会给a打一个正在解析中的tag,没解析完就不会跳过去,解析完了通知我一下 我直接更新(发布订阅)

怎么实现异步?入口文件组织依赖图,依赖图上的每个节点存的是引用地址 ,根据图把整个解析模块分为三个步骤,先执行,其他的pending,执行好了后面的给他一个信号

import也会缓存。

补充知识点

AMD和CMD

ESM漫画图

每个模块拥有自己的实例 必经三步骤