模块化在这个学习过程的位置如上:

JS没有模块化时会产生的问题:

1.经常容易造成全局变量的污染

2.容易发生JS的依赖混乱

模块化的标准

1.CommonJS 社区标准

2.ES Module 官方标准

CommonJS

Common JS 规范:

1.所有的js文件均是一个模块,运行的模块入口模块
2.所有的模块中的全局变量、函数,均不会产生污染
3.当一个模块需要提供一些东西给别的函数使用时,需要把这些东西「导出」
4.当一个模块需要用到别的模块的东西的时候,需要「导入」(模块路径必须以/或./开头)
5.模块有缓存,第一次运行模块后,导出结果会被缓存,之后再使用该模块,直接使用缓存结果

标准类型:社区规范

支持环境:node

依赖类型:动态依赖

Common JS 导出和导入

导出:

1
module.export = 导出的值

导入:

1
require("模块路径")//函数返回模块导出的值

Common JS例子:

config.js:

1
2
3
4
5
6
7
8
9
module.exports = {
wordDuration: 300,//打印每个字的时间间隔
text: `到乡翻似烂柯人,
沉舟侧畔千帆过,
病树前头万木春,
雄关漫道真如铁,
而今迈步从头越。`
}

delay.js:

1
2
3
4
5
6
module.exports = delay;

function delay(ms){
return new Promise((resolve)=>setTimeout(resolve,ms));
}

main.js:这个是主入口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const config = require('./config');
const delay = require('./delay');
const print = require('./print');



async function run() {
let index = 0;
while (index < config.text.length) {
print(index);
await delay(config.wordDuration);
index++;
}
}


run();

print.js:

1
2
3
4
5
6
7
8
9
10
11
12
const config =require('./config');
module.exports = print;



function print(index){
console.clear();
const txt = config.text.substring(0,index+1);
console.log(txt);
}


以上 CMJS 模块化程序实现了给定延迟的输出文章的每个字符,这样做的好处是便于维护和修改。

ES Module

标准类型:官方标准

支持类型:node,浏览器

依赖类型:静态依赖,动态依赖

ES Module导出和导入

导出:

一个模块可以同时存在两种导出方式,最终会合并为一个【对象】导出

注意:导出代码必须为顶级代码,即不可放到代码块中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
一、export const a=l;//具名,常用
export function b(){)/具名,常用
export function c()[)/具名,常用

二、const d = 2;
export{d}//具名

三、const k =10
export{k as temp}/具名

一、export default 3//默认,常用
export default function(){}//默认,常用

二、const e = 4;
export{e as default}/默认

三、const f = 4,g = 5,h = 6
export{f,g,h as default)/基本+默认,这里是f = 4,g = 5 ,default = 6

导入:

针对具名导出和默认导出,有不同的导入语法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//仅运行一次该模块,不导入任何内容
import"模块路径"

//常用,导入属性a、b,放到变量a、b中。a->a,b->b
import {a,b} from"模块路径”

//常用,导入属性default,放入变量c中。default->c
import c from "模块路径"

//常用,default->c,a->a,b->b
import c,{a,b} from "模块路径"

//常用,将模块对象放入到变量obj中
import*as obj from "模块路径"

1
2
3
4
5
6
7
8
9
10
11
//导入属性a、b,放到变量temp1、temp2中
import {a as templ,b as temp2) from"模块路径"

//导入属性default,放入变量a中,default是关键字,不能作为变量名,必须定义别的变量
import {default as a}from"模块路径"

//导入属性default、b,放入变量a、b中
import {default as a,b) from"模块路径"
//以上均为静态导入

import("模块路径")//动态导入,返回一个Promise,完成时的数据为模块对象

动态导入例子:

因为返回的是一个Promise对象,所以也可以用下面这种形式动态导入处理

练习

书写一个ESM模块,查阅文档,导出下面的模块对象

1
2
3
{
a:1
}

你可以写出多少种导出的方式?

再书写一个ESM模块,查阅文档,导入上面的模块对象,你可以写出多少种导入的方式?

导出的方式

1
export const a = 1;
1
2
3
export default{
a:1
}//默认导出
1
2
3
const a = 1;
export {a as b}//具名
export {a as default}//默认

导入的方式

1
2
import {a} from "./test.js";
console.log(a); // 导入属性a,放到变量a中。a->a
1
2
import c from "./test.js"
console.log(c); //导入属性default,放入变量c中。default->c,所以这个只能对导出是默认导出使用
1
2
import * as test from "./test.js"
console.log(test.a); ////常用,将模块对象放入到变量test中