function foo(){
var something = 'cool';
var another = [1, 2, 3];
function doSomething() {
console.log( something );
}
function doAnother() {
console.log( another.join( " ! " ) );
}
}
// 是一个不明显的闭包,doSomething()和doAnother()保持了foo的内部作用域
接下来考虑以下的代码:
function CoolModule() {
var something = "cool";
var another = [1, 2, 3];
function doSomething() {
console.log( something );
}
function doAnother() {
console.log( another.join( " ! " ) );
}
return {
doSomething: doSomething,
doAnother: doAnother
};
}
var foo = CoolModule();
foo.doSomething(); // "cool"
foo.doAnthor(); // 1!2!3
// 上述通过 return 将doSomething和doAnother暴露出来,在js中被称为模块.
从上面可以抽象出模块模式所必须的两个必要条件:
1.必须有外部的封闭函数,该函数必须至少被调用一次(每次调用都会创建一个新的模块实例)
2.封闭函数必须返回至少一个内部函数,这样内部函数才能在私有作用域中形成闭包,并且可以访问或者修改私有的状态.
下面看一个单例模式:
var foo = (function CoolModule() {
var something = 'cool';
var another = [1, 2, 3,];
function doSomething() {
console.log( something );
}
function doAnother() {
console.log( another.join( " ! " ) );
}
return {
doSomething: doSomething,
doAnother: doAnother
}
})();
foo.doSomething(); // cool
foo.doAnother(); // 1!2!3
// 注:上述的CoolModule在执行一次后便释放掉了.
接受参数的模块:
functioin CoolModule(id) {
function identify() {
console.log( id );
}
return {
identify: identify
}
}
var foo1 = CoolModule( "foo 1" );
var foo2 = CoolModule( "foo 2" );
foo1.identify(); // "foo 1"
foo2.identify(); // "foo 2"
// 没啥好说的...
现代的模块机制
var MyModules = (function Manager() {
var modules = {};
function define(name, deps, impl) {
for (var i=0; i < deps.length; i++) {
deps[i] = modules[deps[i]];
}
modules[name] = impl.apply( impl, deps );
}
function get(name) {
return modules[name];
}
return {
define: define,
get: get
};
})();
// 上述定义了一个模块依赖加载器/管理器,下面使用上述的函数来定义模块
MyModules.define( " bar" , [], function() {
function hello(who){
return "Let me introduce: " + who;
}
return {
hello: hello
}
});
MyModules.define( " foo ", ["bar"], function(bar) {
var hungry = "hippo";
function awesome() {
console.log( bar.hello( hungry ).toUpperCase() );
}
return {
awesome: awesome
};
});
var bar = MyModules.get( "bar" );
var foo = MyModules.get( "foo" );
console.log(
bar.hello( "hippo" )
); // Let me introduce: hippo
foo.awesome(); // LET ME INTRODUCE: HIPPO
ES6中的模块
// bar.js
function hello(who) {
return "Let me introduce: " + who;
}
export hello;
// foo.js
import hello from "bar";
var hungry = "hippo";
function awesome() {
console.log(
hello( hungry ).toUpperCase()
);
}
export awesome;
// baz.js
import foo from "foo"; // 书上是module foo from "foo"
import bar from "bar";
console.log(
bar.hellow( "rhino" )
); // Let me introduce: rhino
foo.awesome(); // LET ME INTRODUCE: HIPPO
ES6模块和CommonJS模块的差异:
https://blog.csdn.net/piano9425/article/details/89946163
参考《你不知道的JavaScript》(上卷)P53~P56