模块化之前的JavaScript//Global污染,命名污染function foo(){}//命名空间 NameSpace模式var Module= { foo: function(){},}Module.foo();//减少Global上变量数量,但仍不安全//匿名闭包 IIFE模式var Module = (function(global){ var _private = $(“body”); var foo = function(){console.log(_private)} return { foo: foo }})($)Module.foo();Module._private; // undefinedYUI的模块加载// hello.jsYUI.add(‘hello’, function(Y){ Y.sayHello = function(msg){ Y.DOM.set(el, ‘innerHTML’, ‘Hello!’); }},‘3.0.0’,{ requires:[‘dom’]})// main.jsYUI().use(‘hello’, function(Y){ Y.sayHello(“hey yui loader”);})//comboscript(src=“http://yui.yahooapis.com/combo? 3.0.0/build/yui/yui-min.js& 3.0.0/build/dom/dom-min.js”)COMMONJSNode 应用由模块组成,采用 CommonJS 模块规范。每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。在服务器端,模块的加载是运行时同步加载的;在浏览器端,模块需要提前编译打包处理。所有代码都运行在模块作用域,不会污染全局作用域。模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存。模块加载的顺序,按照其在代码中出现的顺序。//add.jsmodule.exports.add = function(a, b) { return a + b;};//main.jsconst add = require("./add.js").add;module.exports.square_difference = function(a, b) { return add(a, b) * decrease(a, b);};AMD(Asynchronous Module Definition 异步加载模块定义 )如果是浏览器环境,要从服务器端加载模块,这时就必须采用异步模式,因此浏览器端一般采用AMD规范。require.jsvar a = require("./a");a.doSomething();var b = require("./b")b.doSomething();// AMD recommended styledefine([“a”, “b”], function(a, b){ a.doSomething(); b.doSomething();})CMD(Common Module Definition 通用模块定义 )CMD规范专门用于浏览器端,模块的加载是异步的,模块使用时才会加载执行。sea.jsdefine(function(require, exports, module){ var a = require(“a”); a.doSomething(); var b = require(“b”); b.doSomething(); // 依赖就近,延迟执行})ES MouldeES6 模块是动态引用,并且不会缓存值。CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。ES6 模块在对脚本静态分析的时候,遇到 import 就会生成一个只读引用,等到脚本真正执行的时候,再根据这个只读引用,到被加载的那个模块里取值,所以说 ES6 模块是动态引用。 从依赖中引入的模块变量是一个地址引用,是只读的,可以为它新增属性,可是不能重新赋值。import XXX from ‘./a.js’export function a() {}//export default function() {}参考资料:前端模块化详解