JavaScript架構設計Module模式用法實例詳解

伊谢尔伦
發布: 2017-07-24 13:50:46
原創
2065 人瀏覽過

module模式是一個比較流行的設計模式,它可以透過大括號封裝私有的變量,方法,狀態的,透過包裝這些內容,一般全局的物件不能直接訪問,在這個設計模式裡,只回傳一個API,其它的內容全部被封裝成私有的了。

另外,這個模式和自執行的函數表達式比較相似,唯一的差異是module回傳的是對象,而自執行函數表達式回傳的是function。

眾所周知, JavaScript不想其它語言一樣有存取修飾符,不能為每個欄位或方法宣告private,public修飾符,那這個模式我們是如何實現的呢?那就是return一個對象,裡麵包括一些公開的方法,這些方法有能力去呼叫內部的對象。

看一下,下面的程式碼,這段程式碼是一個自執行程式碼,宣告裡包含了一個全域的物件basketModule, basket數組是一個私有的,所以你的整個程式是不能存取這個私有數組的,同時我們return了一個對象,其內包含了3個方法(例如addItem,getItemCount,getTotal),這3個方法可以存取私有的basket數組。


var basketModule = (function() { var basket = []; //private return { //exposed to public   addItem: function(values) {     basket.push(values);   },   getItemCount: function() {     return basket.length;   },   getTotal: function(){     var q = this.getItemCount(),p=0;     while(q--){     p+= basket[q].price;     }     return p;   }  } }());
登入後複製

同時注意,我們return的物件直接賦值給了basketModule,所以我們可以像下面一樣使用:


//basketModule is an object with properties which can also be methods basketModule.addItem({item:'bread',price:0.5}); basketModule.addItem({item:'butter',price:0.3}); console.log(basketModule.getItemCount()); console.log(basketModule.getTotal()); //however, the following will not work: console.log(basketModule.basket);// (undefined as not inside the returned object) console.log(basket); //(only exists within the scope of the closure)
登入後複製

那在各個流行的類別庫(如Dojo, jQuery)裡是如何來做呢?

Dojo

Dojo試圖使用dojo.declare來提供class風格的宣告方式,我們可以利用它來實現Module模式,例如如果你想再store命名空間下宣告basket對象,那麼可以這麼做:


//traditional way var store = window.store || {}; store.basket = store.basket || {}; //using dojo.setObject dojo.setObject("store.basket.object", (function() {   var basket = [];   function privateMethod() {     console.log(basket);   }   return {     publicMethod: function(){       privateMethod();     }    }; }()));
登入後複製

結合dojo.provide一起來使用,非常強大。

YUI

下面的程式碼是YUI原始的實作方式:


##

YAHOO.store.basket = function () { //"private" variables: var myPrivateVar = "I can be accessed only within YAHOO.store.basket ."; //"private" method: var myPrivateMethod = function () { YAHOO.log("I can be accessed only from within YAHOO.store.basket"); } return { myPublicProperty: "I'm a public property.", myPublicMethod: function () { YAHOO.log("I'm a public method."); //Within basket, I can access "private" vars and methods: YAHOO.log(myPrivateVar); YAHOO.log(myPrivateMethod()); //The native scope of myPublicMethod is store so we can //access public members using "this": YAHOO.log(this.myPublicProperty); } }; } ();
登入後複製

jQuery

jQuery裡有很多Module模式的實現,我們來看一個不同的例子,一個library函數宣告了一個新的library,然後創建該library的時候,在document.ready裡自動執行init方法。


function library(module) {   $(function() {     if (module.init) {       module.init();     }   });   return module; } var myLibrary = library(function() {   return {     init: function() {       /*implementation*/       }   }; }());
登入後複製

物件自面量

#物件自面量使用大括號聲明,而且使用的時候不需要使用new關鍵字,如果對一個模組裡的屬性欄位的publice/private不是很在意的話,可以使用這種方式,不過請注意這種方式和JSON的不同。物件自面量:var item={name: "tom", value:123} JSON:var item={"name":"tom", "value":123}。


var myModule = { myProperty: 'someValue', //object literals can contain properties and methods. //here, another object is defined for configuration //purposes: myConfig: { useCaching: true, language: 'en' }, //a very basic method myMethod: function () { console.log('I can haz functionality?'); }, //output a value based on current configuration myMethod2: function () { console.log('Caching is:' + (this.myConfig.useCaching) ? 'enabled' : 'disabled'); }, //override the current configuration myMethod3: function (newConfig) { if (typeof newConfig == 'object') { this.myConfig = newConfig; console.log(this.myConfig.language); } } }; myModule.myMethod(); //I can haz functionality myModule.myMethod2(); //outputs enabled myModule.myMethod3({ language: 'fr', useCaching: false }); //fr
登入後複製

CommonJS

#關於CommonJS的介紹,這裡就不多說了,之前很多文章都有介紹,我們這裡要提一下的是CommonJS標準裡有2個重要的參數exports和require,exports是代表要載入的模組,require是代表這些載入的模組需要依賴它的模組,也需要將它加載進來。


/* Example of achieving compatibility with AMD and standard CommonJS by putting boilerplate around the standard CommonJS module format: */ (function(define){   define(function(require,exports){     // module contents     var dep1 = require("dep1");     exports.someExportedFunction = function(){...};     //...   }); })(typeof define=="function"?define:function(factory){factory(require,exports)});
登入後複製

有很多CommonJS標準的模組加載實現,我比較喜歡的是RequireJS,它能否非常好的加載模組以及相關的依賴模組,來一個簡單的例子,例如需要將圖片轉換成ASCII碼,我們先載入encoder模組,然後取得他的encodeToASCII方法,理論上程式碼應該是如下:


var encodeToASCII = require("encoder").encodeToASCII; exports.encodeSomeSource = function(){   //其它操作以后,然后调用encodeToASCII }
登入後複製

但是上述程式碼並沒用,因為encodeToASCII函數並沒用附加到window物件上,所以不能使用,改進以後的程式碼需要這樣才行:


define(function(require, exports, module) {   var encodeToASCII = require("encoder").encodeToASCII;     exports.encodeSomeSource = function(){     //process then call encodeToASCII   } });
登入後複製

以上是JavaScript架構設計Module模式用法實例詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
最新問題
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!