Home > Article > Web Front-end > Detailed explanation of usage examples of Module pattern in JavaScript architecture design
Module pattern is a relatively popular design pattern. It can encapsulate private variables, methods, and states through curly braces. By packaging these contents, generally global objects cannot be accessed directly. In this design pattern, Only one API is returned, and all other content is encapsulated as private.
In addition, this mode is similar to the self-executing function expression. The only difference is that the module returns an object, while the self-executing function expression returns a function.
As we all know, JavaScript does not have access modifiers like other languages. It cannot declare private and public modifiers for each field or method. So how do we implement this pattern? That is to return an object, which contains some public methods. These methods have the ability to call internal objects.
Look at the following code. This code is a self-executing code. The declaration includes a global object basketModule. The basket array is private, so your entire program cannot access this private array. At the same time, we returned an object, which contains three methods (such as addItem, getItemCount, getTotal). These three methods can access the private basket array.
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; } } }());
Also note that the object we return is directly assigned to basketModule, so we can use it as follows:
//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)
How to do it in various popular libraries (such as Dojo, jQuery)?
Dojo
Dojo tries to use dojo.declare to provide a class-style declaration method. We can use it to implement the Module mode, for example, if you want to store the namespace Declare the basket object below, then you can do this:
//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(); } }; }()));
Used in conjunction with dojo.provide, it is very powerful.
YUI
The following code is the original implementation of 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
There are many implementations of the Module pattern in jQuery. Let’s look at a different example. A library function declares a new library, and then automatically executes init in document.ready when the library is created. method.
function library(module) { $(function() { if (module.init) { module.init(); } }); return module; } var myLibrary = library(function() { return { init: function() { /*implementation*/ } }; }());
Object self-face value
Object self-face value is declared using braces. And you don’t need to use the new keyword when using it. If you don’t care much about the publice/privateness of the attribute fields in a module, you can use this method, but please note that this method is different from JSON. Object self-face: 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
/* 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)});There are many CommonJS standard module loading implementations. The one I prefer is RequireJS. Can it load modules and related dependent modules very well? Here is a simple one For example, if we need to convert a picture into ASCII code, we first load the encoder module, and then get its encodeToASCII method. Theoretically the code should be as follows:
var encodeToASCII = require("encoder").encodeToASCII; exports.encodeSomeSource = function(){ //其它操作以后,然后调用encodeToASCII }But the above code It doesn't work, because the encodeToASCII function is not attached to the window object, so it cannot be used. The future code needs to be improved like this:
define(function(require, exports, module) { var encodeToASCII = require("encoder").encodeToASCII; exports.encodeSomeSource = function(){ //process then call encodeToASCII } });
The above is the detailed content of Detailed explanation of usage examples of Module pattern in JavaScript architecture design. For more information, please follow other related articles on the PHP Chinese website!