js 理解模块化

经常在面试或者其他文章看到关于模块化的问题,之前也只是寥寥看了几次,对于 CommonJSAMDES6也说不出个所以然,于是今天抽空好好看了 红宝书第4版关于模块化的介绍,这里记录一下。

理解模块模式

初衷

在开发中肯定有设计大量三方库或者业务逻辑代码,较好的方式是将其分割为多个小模块,最后以一定的方式连接起来使用,这就是模块化兴起的初衷。

模块化一般包含什么?

模块化通常需要含一下几个点。

模块标识符

模块系统本质上是键/值实体,每个模块都有引用它的标志符,一般是路径或者文件名,部分模块系统也支持自定义标识符,这取决于哪种模块系统。

模块依赖

模块系统的核心就是是管理依赖了,脑海中大概有一张 A→B→C,这样的图就可以明白了。

模块加载

根据依赖,加载模块,在浏览器中只有整个依赖图都加载完成,才可以执行入口模块。

入口

这个就比较好理解了,相互依赖的模块必须指定一个模块作为入口(entry point),这也是代码执行的起点。

异步依赖

因为 JavaScript 可以异步执行,所以如果能按需加载就好了。换句话说,可以让 JavaScript 通知模块系统在必要时加载新模块,并在模块加载完成后提供回调。

// 在模块 A 里面
load('moduleB').then(function(moduleB) {
 moduleB.doStuff();
});
动态依赖

可以在程序结构中动态引入模块

if (loadCondition) {
 require('./moduleA');
} 
静态分析

模块中包含的发送到浏览器的 JavaScript 代码经常会被静态分析,分析工具会检查代码结构并在不实际执行代码的情况下推断其行为。

循环依赖

CommonJS、AMD 和ES6 在内的所有模块系统都支持循环依赖。

上面几点就是模块化的一些基本知识,接下来就看下我们比较关心的也面试偶尔问道的
CommonJSAMDES6

CommonJS

CommonJS 规范主要概述了同步声明依赖的模块定义,一般用于服务端规范,比如node.js(Node.js使用了轻微修改版本的 CommonJS,因为 Node.js 主要在服务器环境下使用,所以不需要考虑网络延迟问题。),CommonJS模块语法是不能直接在浏览器中使用的

使用方法

var moduleB = require('./moduleB');
module.exports = {
 stuff: moduleB.doStuff();
}; 
/**
  一般使用 require 和 module.exports的方式
  可以赋值给变量,也可直接 require 进入,同时不管请求多少次,也只会加载一次
  第一次加载后,模块就会缓存起来,供后续使用
**/ 

AMD

CommonJS 以服务器端为目标环境,能够一次性把所有模块都加载到内存,而 AMD 异步模块定义,是以浏览器为目标。
AMD模块是以函数包装的方式来实现的,就避免暴露全局变量的方式,但是需要AMD加载库来实现。

// ID 为'moduleA'的模块定义。moduleA 依赖 moduleB,
// moduleB 会异步加载
define('moduleA', ['moduleB'], function(moduleB) {
 return {
 stuff: moduleB.doStuff();
 };
}); 

ES6 模块

以上说的两种都需要模块加载器,ES6引入了模块规范,同时原生浏览器也开始支持,融入了 AMD 和 CommonJS的优点


  //像我们平常写的
  import { foo } from './fooModule.js'
  export default 123
  //或者
  <script type="module">
     import './moduleA.js'
  <script>

<script type="module" src="./moduleA.js"></script>
/**
与传统脚本不同,所有模块都会像<script defer>加载的脚本一样按顺序执行。解析到<script
type="module">标签后会立即下载模块文件,但执行会延迟到文档解析完成。
**/

ES6模块的加载

既可以通过浏览器加载,也可以通过打包工具加载

ES6模块部分优点

 1、模块只能加载一次。
 2、模块可以请求加载其他模块。
 3、模块顶级 this 的值是 undefined(常规脚本中是 window)。
 4、模块中的 var 声明不会添加到 window 对象。
 5、ES6 模块是异步加载和执行的,输出值的引用。

几个不同之处

1、CommonJS模块输出是值的拷贝,ES6 Module模块输出的值是引用
2、CommonJS是运行时加载,ES6 Module是编译是输出
3、AMD规范是采用异步方式,依赖前置必须一开始就写好,所有的依赖加载完成后才会执行回调函数里的内容

剩下关于 ES6 模块导入导出的使用方法和规则就不逐一介绍了。

猜你喜欢

转载自blog.csdn.net/qq_45219069/article/details/122446779