相反,我们使用模块的构造函数来实例化一个模块:
var module = new Module();
访问模块的公共 API:
module.sayHello(); // => Hello
这种模式的好处与 IIFE
相同,不过同样它也不能给开发者提供依赖管理的机制。
随着JS的发展,衍生了很多种模块定义语法,每种语法都有各自的优点和缺点。我们称之为模块格式。
模块格式
模块格式是我们用来定义一个模块的语法。
ES6出现之前,JS没有提供官方的模块定义语法。因此,聪明的开发者们提出了多种定义模块的方式。
一些广为使用的模块格式有:
- Asynchronous Module Definition(AMD)
- CommonJS
- Universal Module Definition(UMD)
- System.register
- ES6 Module
下面我们快速过一下每种模块定义的方式。
AMD
AMD模块运行在浏览器环境下,它使用define
函数来定义模块。
define(['dep1', 'dep2'], function (dep1, dep2) { return function () {}; });
CommonJS
CommonJS模块运行在nodejs环境下,它使用 require
管理依赖,module.exports
来定义模块。
var dep1 = require('./dep1'); var dep2 = require('./dep2'); module.exports = function(){ // ... }
UMD
UMD模块可以同时运行在浏览器和Nodejs环境下。
(function (root, factory) { if (typeof define === 'function' && define.amd) { define(['b'], factory); } else if (typeof module === 'object' && module.exports) { module.exports = factory(require('b')); } else { root.returnExports = factory(root.b); } }(this, function (b) { return {}; }));
System.register
System.register
模块的设计意图是在ES5中支持ES6 模块语法:
import { p as q } from './dep'; var s = 'local'; export function func() { return q; } export class C { }
ES6 module
从ES6开始,js提供了原生的模块机制。它使用export
向外暴露API:
// lib.js // 对外导出sayHello export function sayHello(){ console.log('Hello'); } // 不对外导出 function somePrivateFunction(){ // ... }
使用import
导入另一个模块中的API:
import { sayHello } from './lib'; sayHello();
为导入的API使用别名:
import { sayHello as say } from './lib'; say(); // => Hello
导入整个模块:
import * as lib from './lib'; lib.sayHello(); // => Hello
模块中定义默认导出项:
// lib.js // 导出默认函数 export default function sayHello(){ console.log('Hello'); } // 导出非默认函数 export function sayGoodbye(){ console.log('Goodbye'); }