模块化Module
在ES6
之前,社区制定了一些模块加载方案,最主要的有CommonJS
和AMD
两种。前者用于服务器,后者用于浏览器。ES6
在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS
和 AMD
规范,成为浏览器和服务器通用的模块解决方案。
ES6
的模块化的基本规则或特点:
- 每一个模块只加载一次,每一个
JS
只执行一次,如果下次再去加载同目录下同文件,直接从内存中读取。 一个模块就是一个单例,或者说就是一个对象; - 每一个模块内声明的变量都是局部变量, 不会污染全局作用域;
- 模块内部的变量或者函数可以通过
export
导出; - 一个模块可以导入别的模块。
模块功能主要由两个命令构成:export
和import
。export
命令用于规定模块的对外接口,import
命令用于输入其他模块提供的功能。
// ES6模块
import { stat, exists, readFile } from 'fs';
export
命令
一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取模块内部的某个变量,就必须使用export
关键字输出该变量。
- 使用命名导出
使用命名导出语法如下,可导出变量、函数、class
(类)
export { name1, name2, …, nameN };
export { variable1 as name1, variable2 as name2, …, nameN };
export let name1, name2, …, nameN; // also var
export let name1 = …, name2 = …, …, nameN; // also var, const
export function FunctionName() {...}
export class ClassName {...}
导出数据,变量前面加上export
关键字
export var firstName = 'Michael';
export let lastName = 'Jackson';
export const year = 1958;
// 上面的等价于下面的写法,以下这种是常见写法
var firstName = 'Michael';
let lastName = 'Jackson';
const year = 1958;
export {firstName, lastName, year}
导出函数,函数前面加上export
关键字
function multiply(x, y) {
return x * y;
}
export multiply;
// 上面的等价于下面的写法
export function multiply(x, y) {
return x * y;
};
导出类,类前面加上export
关键字
export class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ', ' + this.y + ')';
}
}
- 使用默认导出
因为export default
命令其实只是输出一个叫做default
的变量,所以它后面不能跟变量声明语句,使用默认导出语法如下,
export default expression;
export default function (…) { … } // also class, function*
export default function name1(…) { … } // also class, function*
export { name1 as default, … };
默认导出(函数)
export default function() {}
默认导出(类)
export default class {}
export default
和export
区别
-
export
与export default
均可用于导出常量、函数、文件、模块等,但export default
后不可直接跟var
、let
、const
,也就是其后面不能直接跟变量声明语句;
// 正确
export var a = 1;
// 正确
var a = 1;
export default a; // 将变量a的值赋给变量default
// 错误
export default var a = 1;
- 因为
export default
命令的本质是将后面的值,赋给default
变量,所以可以直接将一个值写在export default
之后,但export
却不能。
// 正确
export default 42;
// 报错(因为没有指定对外的接口)
export 42;
// 正确
var m = 42;
export {m};
可以在其它文件或模块中通过
import+(常量 | 函数 | 文件 | 模块)
名的方式,将其导入,以便能够对其进行使用;使用
export default
命令,为模块指定默认输出,这样就不需要知道所要加载模块的变量名,导入时可以任意为其取名字。但使用export
时,在导入时必须与被导入模块对外接口的名称相同;在一个文件或模块中,
export
、import
可以有多个,export default
仅有一个;通过
export
方式导出,在导入时要加{ }
,export default
则不需要;
// 使用 export
export const str = "blablabla~";
export function log(sth) {
return sth;
}
// 对应的导入方式:
import { str, log } from 'a'; //也可以分开写两次,导入的时候带花括号
// 使用export default
const str = "blablabla~";
export default str;
// 对应的导入方式:
import str from 'a'; //导入的时候没有花括号
- 模块的整体加载
除了指定加载某个输出值,还可以使用整体加载,即用星号(*
)指定一个对象,所有输出值都加载在这个对象上面。
// circle.js
export function area(radius) {
return Math.PI * radius * radius;
}
export function circumference(radius) {
return 2 * Math.PI * radius;
}
现在,加载这个模块。
// 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));
import
命令
使用export
命令定义了模块的对外接口以后,其他 JS
文件就可以通过import命令加载这个模块。
- 导入整个模块的内容
import * as myModule from '/modules/my-module.js';
- 导入单个导出
import {myExport} from '/modules/my-module.js';
- 导入多个导出
import {foo, bar} from '/modules/my-module.js';
- 导入带有别名的导出
import {reallyLongModuleExportName as shortName} from '/modules/my-module.js';
- 导入时重命名多个导出
import {
reallyLongModuleMemberName as shortName,
anotherLongModuleName as short
} from "my-module";
- 导入默认值
// 直接导入默认值
import myDefault from "my-module";
// 与命名空间导入或命名导入一起使用
import myDefault, * as myModule from "my-module";
// 或者
import myDefault, {foo, bar} from "my-module";
参考文章
- export | MDN
- import | MDN
- Module的语法 - 阮一峰