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: hippofoo.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: rhinofoo.awesome(); // LET ME INTRODUCE: HIPPO
ES6模塊和CommonJS模塊的差異:
https://blog.csdn.net/piano9425/article/details/89946163
參考《你不知道的JavaScript》(上卷)P53~P56