• 未来的开发都是“模块化开发
  • 把项目的代码分别写在一个个的模块下,最后把所有的模块合并在一起「webpack/vite」
  • 如果每个模块下,写的代码都是全局声明的,最后在合并的时候,可能导致全局变量污染
  • 解决方法:闭包
  • 问题:都是私有的了,这样模块之前无法相互访问了
  • 我们需要把闭包中的某些东西暴露到外面给其他模块使用

单例设计模式(Single)

  • 最早的模块化开发解决方案
  • 首先基于“闭包”避免了全局变量的污染
  • 再基于“命名空间/模块名”的方式,把闭包中的某些方法暴露出来,供其他模块调用

    1. const 命名空间=(function(){
    2. // 本模块下需要编写的程序
    3. ....
    4. return {
    5. // 需要暴露给外部调用的方法
    6. ...
    7. }
    8. })()
    9. 命名空间.xxx() // 后面的执行都基于命名空间的成员访问方式处理

    弊端:在创建的模块变多的时候,因为模块之间存在“依赖”,所以需要“手动分析”模块之间的依赖,按照顺序,依次在页面中导入对应的模块「这个工作很“恶心”」
    ==> AMD模块化思想「插件:require.min.js,其内部提供了“模块依赖管理”的机制

%95O`H1R(A2HKBAVG3BSJM8.png
image.pngimage.pngimage.pngimage.png

AMD

AMD模块化开发思想和模式

  • 问题: AMD采用的是“前置导入”「把所有依赖的模块,在最开始就指定好」
    • 不方便
    • 每一个模块处理之前,需要把依赖的模块先导入执行,如果依赖的模块比较多,则性能会变慢一些
      • ===> 按需导入 ( CommonJS )

SYBM6AU%6M8FE]GBE(VRJTE.jpgMF3MX~IG(N~7793F2W%M56F.jpg![]2XDH59NKT41N2BJ(LPHQ.jpg![{S}A8]6H}{CSPO7GMZ(I`T.jpg](https://cdn.nlark.com/yuque/0/2023/jpeg/36232707/1689659748725-39728461-a7ed-4e03-8804-344ec6018cff.jpeg#averageHue=%23fbfafa&clientId=u655617f3-13a3-4&from=drop&id=u6bd15bef&originHeight=870&originWidth=1564&originalType=binary&ratio=1.100000023841858&rotation=0&showTitle=false&size=147753&status=done&style=none&taskId=ue35ee2af-005b-4879-9008-99a8abdedaf&title=)

CommonJS

只能在Node(类Node「webpack」)环境下运行,不能用于浏览器端

  • 原先淘宝的一个大神,基于JS重写了一套CommonJS规范「插件:sea.js」,旨在,在浏览器端也支持按需导入(CommonJS规范)

![]D4Q}T4O9{6OO~VUCPY)K9_tmb.jpg(RKGOIW2_W$6TE9M1OK(}YF_tmb.jpg9HPETH9@1G3N3`)AK4R{61X_tmb.jpg
image.png32G5RC9R(YD3`LCFI)SEM5A_tmb.jpg

ES6Module

CommonJS规范只能用于 Node+Webpack 环境下
ES6Module规范(ES规范)只能用于 浏览器+Webpack 环境下

JS可以运行的环境

  • 浏览器「webview」
  • webpack「实现了ES规范和CommonJS规范的混淆」
  • Node
  • …![KZZ7`E5H_NCZQ}B~F_SD5O.jpg

    模块导出:export 或者 export default
    无论基于何种方式,模块导出的永远是一个“Module对象”!!

第一种方式:export

  • 一个模块中可以使用多次,分别导出多项内容
  • 导出的每一项内容,都是给“Module对象”设置相关的成员

第二种方式:export default

  • 一个模块中只能用一次
  • 它是给“Module对象”设置一个叫做default的成员,成员值是导出的内容

在ES6Module的模式下,创建一个JS文件,就相当于创建一个模块,内部编写的代码都是私有的,无需我们自己基于闭包处理image.png
export 后面必须放一个创建变量和值的表达式(不能直接放一个值)

  • export sum //错误
  • export const x = 10 //正确
  • export function fn() { }
  • export const obj = {}

可以放一个类似于“对象”,类似于“代码块”

  • 把大括号中的每一项,作为“Module对象”的成员和对应的值{但是需要这些内容在上面已经声明+定义了}

export {
sum,
name,
// x:10 //错误语法,它不是对象
// const x=10 //错误语法,它不是代码块
}
export default 后面放啥值都可以(但是需要是一个值,不能是创建值的表达式)

  • export default const x = 10 //错误
  • export default function(){} //正确
  • export default sum //正确
  • export default { //正确
    sum
    }

image.png
模块导入:把模块导出的“Module对象”中的每一项内容拿到 => import
import … from ‘模块地址’

  • 相对地址
  • 不能省略后缀名「在webpack中可以省略提前配置好的后缀」

语法一:
import 变量 from ‘./A.js’
不是把“Module对象”整体导入进来赋值给“变量”,而是只拿到了“Module对象.default”属性值「变量=Module对象.default」「换句话说,基于export default xxx导出的内容,用这种方式直接导入」
语法二:
import {x,y} from ‘./A.js’
用解构赋值的方式获取导出的内容,首先不是把“Module对象.default属性值”进行解构赋值;而是直接给“Module对象”解构赋值「换句话来讲,它是获取基于 export let xxx=xxx 这种方式导出的内容」
语法三:
import * as A from ‘./A.js’
把模块导出的“Module对象”中的所有内容都拿到,最后赋值给A「A=Module对象」