JS诞生之初面向简单页面开发, 没有模块的概念。后来页面逐渐复杂, 人类构造到 IIFE 当即执行函数来模拟 模块;以前也有雅虎的实践,使用命名空间 做为模块名。最后衍生出 面向各类使用场景 的 JS 模块标准。例如:
面向浏览器的 AMD
面向Nodejs的 CommonJS
对于这种分裂状态ES标准也在尽力弥合。 可是目前流行的实践是 UMD模式。jquery
AMD 是requirejs 推广产出的规范,主要用于浏览器环境,经过define和require这两个定义模块、调用模块。编程
define("alpha", ["require", "exports", "beta"], function (require, exports, beta) { exports.verb = function() { return beta.verb(); //Or: return require("beta").verb(); } }); // 返回对象的匿名模块 define(["alpha"], function (alpha) { return { verb: function(){ return alpha.verb() + 2; } }; });
require(['foo', 'bar'], function ( foo, bar ) { foo.doSomething(); }); define(function (require) { require(['a', 'b'], function (a, b) { //modules a and b are now available for use. }); });
Node 应用由模块组成,采用 CommonJS 模块规范。
每一个文件就是一个模块,有本身的做用域。在一个文件里面定义的变量、函数、类,都是私有的,对其余文件不可见。
CommonJS 加载模块是同步的,因此只有加载完成才能执行后面的操做。像Node.js主要用于服务器的编程,加载的模块文件通常都已经存在本地硬盘,因此加载起来比较快,不用考虑异步加载的方式,因此CommonJS规范比较适用。但若是是浏览器环境,要从服务器加载模块,这是就必须采用异步模式。因此就有了 AMD CMD 解决方案。api
// a.js // 至关于这里还有一行:var exports = module.exports;代码 exports.a = 'Hello world'; // 至关于:module.exports.a = 'Hello world'; // b.js var moduleA = require('./a.js'); console.log(moduleA.a); // 打印出hello world
兼容 AMD 和 commonjs,也兼容 全局变量定义的 通用的模块化规范浏览器
(function (root, factory) { if (typeof define === 'function' && define.amd) { // AMD define(['jquery'], factory); } else if (typeof exports === 'object') { // Node, CommonJS-like module.exports = factory(require('jquery')); } else { // Browser globals (root is window) root.returnExports = factory(root.jQuery); } }(this, function ($) { function a(){}; // 私有方法,由于它没被返回 (见下面) function b(){}; // 公共方法,由于被返回了 function c(){}; // 公共方法,由于被返回了 // 暴露公共方法 return { b: b, c: c } }));
ES6 在语言标准的层面上,实现了模块功能,并且实现得至关简单,旨在成为浏览器和服务器通用的模块解决方案。其模块功能主要由两个命令构成:export和import。
export命令用于规定模块的对外接口,导出模块暴露的api ;import命令用于输入其余模块提供的功能,引入其余模块。缓存
/** 定义模块 math.js **/ var basicNum = 0; var add = function (a, b) { return a + b; }; export { basicNum, add }; /** 引用模块 **/ import { basicNum, add } from './math'; function test(ele) { ele.textContent = add(99 + basicNum); }
CommonJS 加载的是一个对象(即module.exports属性),该对象只有在脚本运行完才会生成。而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。服务器