JavaScript语言在设计的初期,主要是作为小型的web脚本使用的,并没有模块化的特性。但是,随着这门语言在网页应用中的大规模使用,渐渐出现了各种模块化的规范,比如CommonJS、AMD和CMD等,通过遵守这些规范和约定,可以进行JavaScript的模块化使用。
随着JavaScript语言的发展,在指定ES6标准的时候,加入了模块化的特性。这里做下简单介绍。
1、ES6模块化介绍
1.1 简单说明
ES6 引入了模块化,其设计思想是在编译时就能确定模块的依赖关系,以及输入和输出的变量。
ES6 的模块化分为导出(export) @与导入(import)两个模块。
1.2 特点
ES6 的模块自动开启严格模式,不管你有没有在模块头部加上 use strict;
。
模块中可以导入和导出各种类型的变量,如函数,对象,字符串,数字,布尔值,类等。
每个模块都有自己的上下文,每一个模块内声明的变量都是局部变量,不会污染全局作用域。
每一个模块只加载一次(是单例的), 若再去加载同目录下同文件,直接从内存中读取。
2、使用说明
2.1 基本使用
2.1.1 导出
在/src/compute.js
中定义如下内容,并导出给其它模块使用:
export var testNum1 = 6, testNum2 = 3;
export function add(a, b) {
return a + b;
}
export function minus(a, b) {
return a - b;
}
export function multiply(a, b) {
return a * b;
}
export function divide(a, b) {
return a / b;
}
也可以在最后一起导出,如下写法和上面是等价的:
var testNum1 = 6, testNum2 = 3;
function add(a, b) {
return a + b;
}
function minus(a, b) {
return a - b;
}
function multiply(a, b) {
return a * b;
}
function divide(a, b) {
return a / b;
}
//这里导出一堆变量
export {add, minus, multiply, divide, testNum1, testNum2}
也可以在导出时,指定别名如下:
var testNum1 = 6, testNum2 = 3;
function jia(a, b) {
return a + b;
}
function jian(a, b) {
return a - b;
}
function cheng(a, b) {
return a * b;
}
function chu(a, b) {
return a / b;
}
//这里导出一堆变量
export {jia as add, jian as minus, cheng as multiply, chu as divide, testNum1, testNum2}
2.1.2 导入
在/src/main.js
中引入前面的导入:
import {add, minus, multiply, divide, testNum1, testNum2} from './compute.js'
var num1 = 10, num2 = 2;
alert("testNum1: " + testNum1 + ", testNum2: " + testNum2 + " " + add(num1, num2) + " " + minus(num1, num2)+ " " + multiply(num1, num2)+ " " + divide(num1, num2));
导入的文件中,也可以不加后缀,如下写法是等价的:
import {add, minus, multiply, divide, testNum1, testNum2} from './compute'
var num1 = 10, num2 = 2;
alert("testNum1: " + testNum1 + ", testNum2: " + testNum2 + " " + add(num1, num2) + " " + minus(num1, num2)+ " " + multiply(num1, num2)+ " " + divide(num1, num2));
也可以在导入时,通过as改变变量的名字。如下代码正常运行:
import {add as jia, minus as jian, multiply as cheng, divide as chu, testNum1, testNum2} from './compute.js'
var num1 = 10, num2 = 2;
alert("testNum1: " + testNum1 + ", testNum2: " + testNum2 + " " + jia(num1, num2) + " " + jian(num1, num2)+ " " + cheng(num1, num2)+ " " + chu(num1, num2));
也可以采用整体加载导入的方式,即用星号(*
)指定一个对象,所有输出值都加载在这个对象上面。如下:
import * as tmp from './compute.js'
var num1 = 10, num2 = 2;
alert("testNum1: " + tmp.testNum1 + ", testNum2: " + tmp.testNum2 + " " + tmp.add(num1, num2) + " " + tmp.minus(num1, num2)+ " " + tmp.multiply(num1, num2)+ " " + tmp.divide(num1, num2));
2.1.3 只读属性说明
不允许在加载模块的脚本里面,改写接口的引用指向,即可以改写 import 变量类型为对象的属性值,不能改写 import 变量类型为基本类型的值。
import {a} from "./xxx.js"
a = {}; // error
import {a} from "./xxx.js"
a.foo = "hello"; // a = { foo : 'hello' }
2.2 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"; // 不需要加{}, 使用任意变量接收
2.2.1 导出
/src/year.js
:
export default {
year: 2022,
zodiac: 'tiger'
}
2.2.2 导入
/src/main.js
:
import temp from './year.js'//这里不用加大括号
alert("year: " + temp.year + ", zodiac: " + temp.zodiac);
参考资料
- 4.4 ES6 模块
- 关于Node.js
- JavaScript模块化:从闭包到ES Module