JavaScript在ES6之前一直没有标准的模块化机制,这对编写大型项目非常不利。之后出现了CommonJS规范(用于NodeJS),AMD规范等,实现了JavaScript的模块化机制。ES6根据这些已有的规范,推出了语言级的模块化标准。
export
可以暴露变量、类或是方法。下面代码中,通过export
暴露了类的定义:
point.js
export class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ',' + this.y + ')';
}
}
export class ColorPoint extends Point{
constructor(x, y, color) {
super(x, y);
this.color = color;
}
toString() {
return '(' + this.x + ',' + this.y + ',' + this.color + ')';
}
}
在另一个文件中可以通过import
引入模块中暴露的变量、方法或类:
index.js
import {Point,ColorPoint} from './point';
let c = new ColorPoint(1, 2, 'RED');
console.log(c.toString());
我们可以将其理解为解构赋值,export
输出一个含有多个导出内容的对象,import
时使用对应的字段来接收。point
则是文件名,其后缀.js
可以省略,当然写上也没有问题。
注:实际上,使用CommonJS模块规范的Node无法运行上述代码,浏览器中也无法直接运行,但我们可以配置webpack
工具将上述代码打包来进行测试,具体请参考webpack
相关章节。
let i = 1;
let foo = function () {
};
export {i, foo};
前面的写法中,我们直接把export
关键字加到了class
前面,这里我们也可以使用大括号,一次暴露多个内容。
我们可以使用export default
指定一个默认导出内容。
export default class ColorPoint extends Point{ ... }
引用时就可以不必使用大括号了:
import ColorPoint from './point';
默认导出的内容,实际上我们可以对其任意命名,比如上述导入代码写作import aaa from './point';
也是可以的。
非默认导出的内容,我们可以使用as
关键字给暴露的内容指定一个别名。
export {i as magicNum, foo};
上面我们学习了如何在工程内导入文件定义的内容,那么如何编写一个独立的模块,发布到npm
仓库,再在其他工程引入呢?
这也其实比较简单,关键是创建好package.json
就行了。
package.json
{
"name": "mylib",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
package.json
中,最重要的两个字段:
name
:模块名,我们从其他工程引入该模块代码时需要这个名字main
:入口文件,我们模块导出的内容都需要在这个入口文件中统一暴露index.js
export default {
add: function(a, b) {
return a + b;
}
};
这样,我们就编写好一个模块了。
至于如何发布模块,请参考npm
相关章节。
node_modules
中的模块我们在工程中安装好模块后,模块的代码会拷贝到node_modules
中。工程node_modules
目录下的模块,会在模块的默认搜索路径下,因此我们不需要手动指定如../../util
这种相对路径,在任意位置都能引用。
假设我们的模块名为mylib
,其入口文件为index.js
,那么index.js
中暴露的内容就可以import mylib from 'mylib';
这种写法引入。
导入模块代码:
import mylib from 'mylib';
如果模块暴露多个内容,也是可以用import { a, b, c} from 'mylib';
这种形式引入多个内容的。