JS语言本身没有模块概念,为了让JS支持模块化,ServerJS(后更名为CommonJS)社区大牛们推出了Module 1.0规范。后来为了可用于浏览器端,制定了名为AMD规范,并且推出了requireJS这个框架。由于AMD与CommonJS规范相去甚远,CommonJS的拥护者认为,浏览端也可以实现CommonJS的规范,于是稍作改动,形成了CMD规范,并且推出了seajs这个框架。正在AMD与CMD打得火热的时候,ECMAScript6给JS本身定了一个模块加载的功能,ES6表示“你们也别争了,JS模块有原生的语法了”。
引出格式
// 1
export let a = 1
// 2
let b = 2
let f = 'str'
export {b, f}
// 3
let c = 3
export {c as d}
// 4
let m = 'aaa'
export default m
CommonJS引入,相当于ES6的 import * as xxx
方式
let xxx = require('../utils/xxx.js')
let a = xxx.a
let m = xxx.default
ES6引入
import {a} from '../utils/xxx.js'
import * as xxx from '../utils/xxx.js'
let a = xxx.a
let m = xxx.default
import m from '../utils/xxx.js'
David Herman 关于引入multi-export modules的proposal:
import * as fs from "fs"; // importing the named exports as an object
import Dict from "dict"; // importing a default export, same as ever
rather than:
import "fs"; // state the dependency
var fs = this.get("fs");
引出格式
const style = {
link: '111',
error: '222'
}
module.exports = style
CommonJS引入
let style = require('../utils/xxx.js')
ES6引入
import style from '../utils/ConsoleStyle.js'
引出格式
const style = {
link: '111',
error: '222'
}
module.exports = {style: style, a: 1}
CommonJS引入
let xxx = require('../utils/xxx.js')
let style = xxx.style
ES6
ECMAScript 6 modules must work independently of whether the engine loads modules synchronously (e.g. on servers) or asynchronously (e.g. in browsers) – Dr. Axel Rauschmayer
Import can be asynchronous (and in current ES6 Module Loader, it in fact is) and can perform a little better. – Amit
You can use named imports to selectively load only the pieces you need. That can save memory.
//------ lib.js ------
export let counter = 0;
export function inc() {
counter++;
}
//------ main.js ------
import { inc, counter } from 'lib';
console.log(counter); // 0
inc();
console.log(counter); // 1
CommonJS
You can have dynamic loading where the loaded module name isn’t predefined /static, or where you conditionally load a module only if it’s “truly required” (depending on certain code flow).
Loading is synchronous. That means if you have multiple requires, they are loaded and processed one by one.
//------ a.js ------
exports = function(s) { ... }
//------ b.js ------
let a = require('./a') //{}
Because B’s variable a would still refer to A’s original exports object. (空对象)
//------ lib.js ------
exports.counter = 0;
exports.inc = function() {
this.counter++;
}
//------ main.js ------
let foo = require('./lib').inc
let counter = require('./lib').counter
inc();
console.log(counter); // 0
//------ a.js ------
var b = require('b');
exports.foo = function () { ... };
//------ b.js ------
var a = require('a'); // (1)
// 此时a.foo == undefined
exports.bar = function () {
a.foo(); // OK (2)
};
//------ main.js ------
var a = require('a');
As a general rule, keep in mind that with cyclic dependencies, you can’t access imports in the body of the module. That is inherent to the phenomenon and doesn’t change with ECMAScript 6 modules.
this === module.exports //true
this === exports //true