目录
六、其他前端模块化规范(CommonJS、AMD 和 CMD 规范)
在 ES6 之前,实现模块化使用的是 CommonJS 和 AMD 两种。前者更适合用于服务器,后者更适合用于浏览器。RequireJS 就是 AMD 最流行的实现。ES6 实现了模块功能。
ES6 的模块自动采用严格模式,不管你有没有在模块头部加上 "use strict";。详情请戳:https://blog.csdn.net/mChales_Liu/article/details/106905560
ES6 的模块功能主要由两个命令构成:export 和 import。
- export 命令用于规定模块的对外接口。
- import 命令用于输入其他模块提供的功能。
一、export 命令
一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取模块内部的某个变量,就必须使用export关键字输出该变量。
1、export 命令的两种写法
①、逐一输出法:
// profile.js
export var firstName = 'Michael';
export var lastName = 'Jackson';
export var year = 2020;
②、末尾一起输出法(推荐):
// profile.js
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 2020;
export { firstName, lastName, year };
上面代码是 profile.js 文件,保存了用户信息。ES6 将其视为一个模块,里面用 export 命令对外部输出了三个变量。
2、export 命令的应用
export 命令既可以输出变量,又可以输出函数或类(class)。
// export 命令输出变量
export var year = 2020;
// export 命令输出函数
export function multiply(x, y) {
return x * y;
};
// export 命令输出类
export class Person(name, age) {
return `我是${name}, 今年${age}岁了。`;
};
二、import 命令
使用 export 命令定义了模块的对外接口以后,其他 JS 文件就可以通过 import 命令加载这个模块。
通过 import 命令输入的模块,编译时才会加载,也叫静态加载。
1、import 命令的写法
// main.js
import { firstName, lastName, year } from './profile.js';
function setName(element) {
element.textContent = firstName + ' ' + lastName;
}
2、from 关键字指定模块文件的位置
import 后面的 from 关键字用来:指定模块文件的位置。有以下三点需要注意:
- 可以是相对路径,也可以是绝对路径。
- .js 后缀可以省略。
- 如果只是模块名,不带有路径,那么必须有配置文件,告诉 JavaScript 引擎该模块的位置。
import {myMethod} from 'util';
上面代码中,util是模块文件名,由于不带有路径,必须通过配置,告诉引擎怎么取到这个模块。
3、import 命令的特性
- import 命令输入的变量都是只读的。
- import 命令具有提升效果,会提升到整个模块的头部,首先执行。
①、import 命令输入的变量都是只读的。
import {a} from './xxx.js'
a = {}; // Syntax Error : 'a' is read-only;
上面代码中,脚本加载了变量a,对其重新赋值就会报错,因为a是一个只读的接口。但是,如果a是一个对象,改写a的属性是允许的。
import {a} from './xxx.js'
a.foo = 'hello'; // 合法操作
②、import命令具有提升效果,会提升到整个模块的头部,首先执行。
foo();
import { foo } from 'my_module';
上面的代码不会报错,因为import的执行早于foo的调用。这种行为的本质是,import命令是编译阶段执行的,在代码运行之前。
4、import() 函数实现动态加载模块
ES2020 提案 引入 import() 函数,支持动态加载模块——按需加载模块。
import() 返回一个 Promise 对象。
例如:
const main = document.querySelector('main');
import(`./section-modules/${someVariable}.js`)
.then(module => {
module.loadPageInto(main);
})
.catch(err => {
main.textContent = err.message;
});
import() 函数可以用在任何地方,不仅仅是模块,非模块的脚本也可以使用。没有提升效果,运行到这行代码时才会执行。
import() 函数类似于 Node 的 require() 方法,区别主要是前者是异步加载,后者是同步加载。
三、export default 命令
当用户不知道知道所要加载的变量名或函数名时,就要用到 export default 命令,为模块指定默认输出了。
- 在一个文件或模块中,export、import 可以有多个,export default 仅有一个。
- export default 中的 default 是对应的导出接口变量。
- 通过 export 方式导出,在导入时要加{ },export default 则不需要。
- export default 向外暴露的成员,可以使用任意变量来接收。
var a = "My name is Tom!";
export default a; // 仅有一个
export default var c = "error";
// error,default 已经是对应的导出变量,不能跟着变量声明语句
import b from "./xxx.js"; // 不需要加{}, 使用任意变量接收
四、as 关键字重命名模块的变量
as 关键字用来:重命名模块的变量。
1、输出时重命名模块的变量
function v1() { ... }
function v2() { ... }
export {
v1 as streamV1,
v2 as streamV2
};
2、输入时重命名模块的变量
import { lastName as surname } from './profile.js';
五、模块的整体加载
除了指定加载某个输出值,还可以使用整体加载,即用星号(*)指定一个对象,所有输出值都加载在这个对象上面。
举个栗子:
导出一个模块:
// circle.js
function area(radius) {
return Math.PI * radius * radius;
}
function circumference(radius) {
return 2 * Math.PI * radius;
}
export {area, circumference}
加载这个模块:
// main.js
import { area, circumference } from './circle';
console.log('圆面积:' + area(4));
console.log('圆周长:' + circumference(14));
上面写法是逐一指定要加载的方法,整体加载的写法如下:
import * as circle from './circle';
console.log('圆面积:' + circle.area(4));
console.log('圆周长:' + circle.circumference(14));
六、其他前端模块化规范(CommonJS、AMD 和 CMD 规范)
请戳这里:https://blog.csdn.net/mChales_Liu/article/details/109466163