CommonJS 重点
AMD
CMD
ES6 模块化 重点
每个模块尽量简洁,不超过50行代码,便于维护和复用,避免全局污染
nodejs直接运行某个js文件,该文件被称之为入口文件;
nodejs 遵循es标准,单由于脱离了浏览器环境,因此:
1、你可以在nodejs中使用es标准的任何语法或api,例如:循环、判断、数组、对象等
2、你不能在nodejs中使用浏览器的web api,例如:dom对象,window对象,document对象等
模块:模块就是一个js文件,它实现了一部分功能,并隐藏自己的内部实现,同时提供了一些接口供其他模块使用
模块有两个核心要素:隐藏和暴露
隐藏的是自己内部的实现
暴露的是希望外部使用的接口
任何一个正常的模块化标准,都应该默认隐藏模块中的所有实现,而通过一些语法或api调用来暴露接口
暴露接口的过程即模块的导出
当通过某种语法或api去使用一个模板时,这个过程叫做模块的导入
CommonJS规范(静态依赖)
commonjs使用exports导出模块,require导入模块
nodejs中导入模块,使用相对路径,并且必须使用./或../开头
CMJ 具体规范如下:
1、如果一个js文件中存在exports或require,该文件是一个模块
2、模块内的所有代码均为隐藏代码,包括全局变量、全局函数,这些全局的内容均不应该对全局变量造成任何污染
3、如果一个模块需要暴露一些API提供给外部使用,需要通过exports导出,exports是一个空的对象,你可以为该对象添加任何需要导出的内容
4、如果一个模块需要导入其他模块,通过require实现,require是一个函数,传入模块的路径即可返回该模块导出的整个内容
nodejs对commonjs的实现:
1、为了保证高效的执行,仅加载必要的模块,nodejs只有执行到require函数时才会加载并执行模块
2、为了隐藏模块中的代码,nodejs执行模块时,会将模块中的所有代码放置到一个函数中执行,以保证不污染全局变量
(function(){//模块中的代码})()
3、为了保证顺利的导出模块内容,nodejs做了一下处理
1)在模块开始执行前,初始化一个值module.exports={}
2)module.exports即模块的导出值
3)为了方便开发者便捷的导出,nodejs在初始化module.exports后,又声明了一个变量exports=module.exports,在exports中加属性,然后进行导出
(function(module){
module.exports = {};
var exports = module.exports;
//模块中的代码
return module.exports;
})()
4)为了避免反复加载同一个模块,nodejs默认开启了模块缓存,如果加载的模块已经被加载过了,则会自动使用之前的导出结果
commonjs是同步的
不能在浏览器运行的原因:
1、远程加载js浪费时间
2、模块代码需要放到函数中执行
要解决这两个问题,出现了AMD和CMD
AMD全称是Asynchronous Module Definition 即异步模块加载机制
require.js实现了AMD规范,在AMD中,导入和导出模块的代码,都必须放置在define函数中
define([依赖的模块列表],function(模块名列表){
//模块内部的代码
return导出的内容
})
CMD全称是COMMON Module Definition 公共模块定义规范
sea.js实现了CMD规范
在cmd中,导入和导出模块的代码,必须放置在define函数中
define((require,exports,module)=>{
//模块内部代码
})
Commonjs依赖延迟声明:
优点:某些时候可以提高效率
缺点:无法在一开始确定模块依赖关系
ES6模块化(ESM)的特点
:(动态依赖、静态依赖)
1、使用依赖 预声明 的方式导入模块
2、灵活的多种导入导出方式
3、规范的路径表示法:所有路径必须以./或../开头
模块的引入,注意:这一部分非模块化
目前,浏览器使用以下方式引入一个ES6模块文件:
<script src= "入口文件" type="module">
ES6的模块导入导出分为两种:
1、基本导入导出
导出:(由于基本导出必须具有名称,所以要求导出内容必须跟上声明表达式或具名符号)
export 基本声明表达式
(export var a =1)
或 export {具名符号}
(var age = 18;
export{age}; )
导入:(由于使用的是预依赖加载,因此导入其他任何模块,都需要写在所有代码之前)
import{导出的符号列表} from "模块路径"
导入细节:
1)导入时,可以通过关键字as对导入的符号进行重新命名
import{b as c} from "模块路径"
2)导入时使用的符号是常量,不可修改
3)可以使用*号导入所有的基本导出,行成一个对象
import * as d from "模块路径"
4)有一些初始化代码,只需要导入,不需要运行,可以直接写代码:
import "模块路径"
2、默认导入导出
每个模块,除了允许有多个基本导出之外,还允许有一个默认导出,由于只有一个,因此无需取名,每个模块不能出现多个默认导出语句
默认导出:
export default 默认导出的数据
或 export{默认导出的数据 as default}
默认导入:
import 接收变量名 from “模块路径”
如果希望同时导入某个模块的默认导出和基本导出,可以使用下面的语法:
import 接收默认导出的变量,{接收基本导出的变量} from “模块路径”
如果使用*号,会将模块的所有默认导出和基本导出聚合到一个对象中,默认导出会作为属性default存在
以上均为静态导入
1、静态导入的代码必须在代码顶端,也不可放在代码块中
2、静态导入的代码绑定的符号是常量,不可更改
动态导入:
import("模块路径")
返回一个promise,完成时的数据为模块对象
ES6模块化细节:
1、尽量导出不可变值
2、可以使用无绑定的导入用于执行一些初始化代码;import "模块路径"
3、可以使用绑定再导出,来重新导出来自另一个模块的内容
export (绑定的标识符) from "模块路径"