Home  >  Article  >  Web Front-end  >  Detailed explanation of usage examples of Module pattern in JavaScript architecture design

Detailed explanation of usage examples of Module pattern in JavaScript architecture design

伊谢尔伦
伊谢尔伦Original
2017-07-24 13:50:462102browse

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

##I won’t say much about the introduction of CommonJS here. Many articles have introduced it before. What we want to mention here is that there are two important parameters in the CommonJS standard, exports and require. Exports represents the modules to be loaded, and require represents that these loaded modules need to depend on other modules. Also It needs to be loaded in.


/*
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!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn