模块化 && 前端
目前实现模块化的规范主要有:
CommonJS
(同步)CMD
(同步)AMD
(异步)ES6(ESM)
模块 (异步)
主要介绍 CommonJS 和 ESM
Commonjs
- 采用同步加载模块的方式,也就是说只有加载完成,才能执行后面的操作。
CommonJS
代表:Node
应用中的模块 - 它使用
require
引用和加载模块,exports
定义和导出模块,module 标识模块。使用 require 时需要去读取并执行该文件,然后返回 exports 导出的内容。 - 如果我们在某个代码模块里使用
CommonJS
的方法require了一个模块,而这个模块需要通过http请求从服务器去取,如果网速很慢,而CommonJS
又是同步的,所以将阻塞后面代码的执行,从而阻塞浏览器渲染页面,使得页面出现假死状态。
node中:
node在执行一个文件时,会在文件中生成一个exports
和 module
对象,module
对象又有一个exports
属性。exports
和 module.exports
的关系:两者都是指向同一个对象;
export
对象:由于
module.exports
单词写起来比较复杂,为了简化向外共享成员的代码,Node
提供了 exports
对象。两者皆可使用(默认情况下,exports 和 module.exports
指向同一个对象,使用 require()
方法导入模块时,导入的结果,永远以 module.exports
指向的对象为准 换句话说最终共享的结果,还是以 module.exports
指向的对象为准)
用法:
// 定义模块math.js
var basicNum = 0;
function add(a, b) {
return a + b;
}
module.exports = { //在这里写上需要向外暴露的函数、变量
add: add,
basicNum: basicNum
}
/** 必须加./路径,不加的话只会去node_modules文件找 **/
// 引用自定义的模块时,参数包含路径,可省略.js
var math = require('./math');
math.add(2, 5);
// 引用核心模块时,不需要带路径
var http = require('http');
http.createService(...).listen(3000);
ES6(ESM)
ES6 模块化规范是浏览器端与服务器端通用的模块化开发规范
- ES6设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量,所以说ES6是编译时加载
- ES6模块不是对象,而是通过export命令显式指定输出的代码,输入时也采用静态命令的形式。
用法:
1、默认导出、导入
//01_m1.js
let n1 = 10 // 定义模块私有成员n1
let n2 = 20 // 定义模块私有成员n2 (外界访问不到n2,因为它没有被共享出去)
function show(){} // 定义私有模块方法show
export default{ //使用export default 默认导出语法,向外共享n1 和 show 两个成员
n1,
show
}
//从 01_m1.js 模块中导入 export default 向外共享的成员
//使用m1 成员进行接收(也可以使用其他合法命名如:ysl)
import m1 from './01_m1.js'
//打印输出的结果为:
//{n1:10, show:[Function: show]}
console.log(m1)//(注:每个模块中,只允许使用唯一的一次 export default,否则会报错!)
2、按需导出、导入
// 当前模块为03_m2.js
//向外按需导出变量s1
export let s1 = 'aaa'
//向外按需导出变量s2
export let s2 = 'ccc'
//向外按需导出方法say
export function say(){}
// 导入模块成员
import { s1, s2, say } from './03_m2.js'
console.log(s1); //打印输出 aaa
console.log(s2); //打印输出 ccc
console.log(say); //打印输出 [Function: say]
注:
- ① 每个模块中可以使用多次按需导出
- ② 按需导入的成员名称必须和按需导出的名称保持一致
- ③ 按需导入时,可以使用as 关键字进行重命名
- ④ 按需导入可以和默认导入一起使用
3、导入并执行模块中的代码
//ysl.js
for(let i = 0; i < 5; i++ ){
console.log(i)
}
//使用的文件
import './ysl.js'
//将打印0,1,2,3,4三、commonjs 和 ESM区别
区别
CommonJS(require)
-
1.对基本类型,属于复制;
a = require(b)
,b会被a缓存。 -
2.对于复杂数据类型,属于浅拷贝,浅拷贝的话就存在一个问题,修改a的话b也会被修改。(Q2又引出一个问题:怎么阻止这种情况发生?)。
-
3.在使用
require
命令加载模块时,就会运行整个模块的代码(同步加载)。 -
4.使用
require
命令加载加载过的模块时,不会再执行一次而是从缓存中取,除非清除缓存。