模块化之前的 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; // undefined
YUI 的模块加载
// hello.js
YUI.add(‘hello’, function(Y){
Y.sayHello = function(msg){
Y.DOM.set(el, ‘innerHTML’, ‘Hello!’);
}
},’3.0.0′,{
requires:[‘dom’]
})
// main.js
YUI().use(‘hello’, function(Y){
Y.sayHello(“hey yui loader”);
})
//combo
script(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.js
module.exports.add = function(a, b) {
return a + b;
};
//main.js
const 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.js
var a = require(“./a”);
a.doSomething();
var b = require(“./b”)
b.doSomething();
// AMD recommended style
define([“a”, “b”], function(a, b){
a.doSomething();
b.doSomething();
})
CMD(Common Module Definition 通用模块定义)CMD 规范专门用于浏览器端,模块的加载是异步的,模块使用时才会加载执行。sea.js
define(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() {}
参考资料:前端模块化详解