1. 程式人生 > >模組與閉包

模組與閉包

function Module(){
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 = Module();

foo.doSomething();

foo.doAnother();

這個模式在javascript中被稱為模組。

首先,Module()只是一個函式,通過呼叫它來建立一個模組例項。

其次,Module()方法返回一個用物件字面量語法來表示的物件。這個物件中包含對內部函式而不是內部資料變數的引用,從而來確保內部資料變數的私有化。可以將這個返回的物件看作是模組的公共API。

注:doSomething()和doAnother()函式具有涵蓋模組例項內部作用域的閉包。

模組模式需要具備兩個必要的條件:

1. 必須有外部的封閉函式,該函式必須至少被呼叫一次(每次呼叫都會建立一個新的模組例項)

2. 封閉函式必須返回至少一個內部函式,這樣內部函式才能在私有作用域中形成閉包,並且可以訪問或者修改私     有的狀態。

當然,我們也可以通過一個簡單的改進來實現單例模式:

var foo = (function Module(){
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();
foo.doAnother();

現代的模組機制(AMD):

var MyModule = (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[naem];
}

return {
define: define,
get: get
};
})();

怎麼使用呢?

   MyModule.define("bar", [], function(){
   function hello(who){
   return "my name is" + who;
   }
   return {
   hello: hello
   } 
   });


   MyModule.define("foo", ["bar"], function(bar){
   var hungry = "jianlu";
   function awesome(){
   console.log( bar.hello( hungry ).toUpperCase() );
   }
   return {
   awesome: awesome
   } 
   });

   var bar = MyModule.get("bar");
   var foo = MyModule.get("foo");
   console.log( bar.hello("jianlu") );
   foo.awesome();   

未來的模組機制

在ES6中,一個檔案就是一個模組:

bar.js

function hello(who){
       return "my name is" + who;
}

export hello;

foo.js

 //僅從“bar”模組匯入hello

import  hello from "bar";

 var hungry = "jianlu";

function awesome(){
console.log( hello( hungry ).toUpperCase() );
}

 export awesome;

baz.js

 module foo form "foo";

module bar form "bar";

 console.log( bar.hello("jianlu") );

 foo.awesome();

注: import可以將一個模組中的一個或多個API匯入到當前的作用域中,並分別繫結在一個變數上。

 module會將整個模組的API匯入到並繫結到一個變數上。