历史
-
Javascript 一直没有模块体系,无法将一个大程序拆分成互相依赖的小文件。
-
ES6 之前,社区指定了一些模块加载方案,主要有 CommonJS(用于服务器) 和 AMD(用于浏览器) 。
-
ES6 :实现了Module(模块功能),完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。
ES6 的模块自动采用严格模式,不管你有没有在模块头部加上
"use strict";
运行时加载 和 编译时加载(静态加载)
运行时加载:CommonJS 。 CommonJS 模块就是对象,需要加载所需模块整体后,运行时生成一个对象,才能从对象上读取所需的方法
// CommonJS模块
let { stat, exists, readfile } = require('fs');
// 等同于
let _fs = require('fs');
let stat = _fs.stat;
let exists = _fs.exists;
编译时加载/静态加载:ES6 Module。 Module 模块不是对象,可以在编译时就完成模块加载,并且只加载模块上所需的方法,其他方法不加载。
// ES6模块
import { stat, exists, readFile } from 'fs';
ES6 模块功能主要由 export 和 import 两个命令构成。
- export 规定模块对外暴露的接口
- import 输入其他模块提供的接口
- 一个模块就是一个独立的文件,没有使用 export 关键字输出的变量,外部无法获取
export 命令
输出变量
// a.js
export var name = 'lili';
// 等价于
var name = 'lili';
var info = { age: 18 };
export { name, info } // 推荐使用大括号输出一组变量放在脚本尾部
// 使用 as 关键字重命名,可以实现同一个变量重复输出两次
export { name as lastName, name as firstName }
输出函数或类(class)
export function sayHello() { ... }
import 命令
- 使用
export
命令定义了模块的对外接口以后,其他 JS 文件就可以通过import
命令加载这个模块; import
命令接受一对大括号,大括号里面的变量名,必须与被导入模块(a.js)对外接口的名称相同;import
命令输入的变量都是只读,可以视为一个常量,对其重新赋值会报错,但如果该变量是一个对象,是允许修改对象的属性,修改后其他模块也可以读取到改后的值。(不建议修改,难查错)import
命令具有提升效果,会自动提升到整个模块的头部,首先执行
输入
// b.js
import { name, info } from './a.js'
// 使用 as 关键字重命名
import { name as username } from './a.js'
修改
name = 'tom' // Syntax Error : 'username' is read-only;
info.age = 20 // 合法操作
只执行,不输入任何值
import 'lodash'
整体加载 *
// * 表示整体加载, as 后紧跟着重命名
import * as VueRouter from 'vue-router'
export default 命令
从前面的例子可以看出,使用import
命令的时候,用户需要知道所要加载的变量名或函数名,否则无法加载。但是,用户肯定希望快速上手,未必愿意阅读文档,去了解模块有哪些属性和方法。
为了给用户提供方便,让他们不用阅读文档就能加载模块,就要用到export default
命令,为模块指定默认输出。
- 这时
import
后面不需要大括号 - 一个模块只能有一个默认输出,
export default
命令只能用一次 export default
后无论是否是匿名函数,import
加载时都视同匿名函数,允许你为它取任意名字export default
其实只是输出一个叫做 default 的变量,所以它后面不能跟变量的声明语句
指定默认输出
// a.js
export default function() { ... }
// 等价于
export default function say() { ... }
// 等价于
function say () {...}
export default say;
// x 错误写法
export default const say = function() {}
为默认输出(匿名函数)指定任意名字后输入,
// b.js
import sayHello from './a.js';
sayHello();
ES2020 引入 import() 函数,支持动态加载模块
- import() 是异步加载,返回一个Promise 对象
import('./myModule.js')
.then(res => {
// ...·
});
浏览器加载 ES6 模块
- 需要加入 type = "module"属性;
- 浏览器对于带有type="module"的
<script>
,都是异步加载,不会造成堵塞浏览器,即等到整个页面渲染完,再执行模块脚本,等同于打开了<script>
标签的defer属性。
<script type="module" src="./foo.js"></script>
<!-- 等同于 -->
<script type="module" src="./foo.js" defer></script>
♥ ♥ ♥
如果本文给你带来了一丢丢帮助,麻烦动动手指头帮我点个赞收藏加关注,或者评论区给我留留言 ღ( ´・ᴗ・` )ღ
♥ ♥ ♥