JavaScript Modular Programming

Source: Internet
Author: User

Http://www.ruanyifeng.com/blog/2012/10/javascript_module.html JavaScript Modular Programming (i): The writing of modules

first, the original wording

A module is a set of methods for implementing a particular function.

Just put the different functions (and the variables of the record state) simply together, even a module.

function M1 () {
    //...
}
function m2 () {
    //...
}

The above function m1 () and M2 () to form a module. When used, call directly on the line

The disadvantage of this approach is obvious: "pollution" of the global variable, can not guarantee that no variable name conflicts with other modules, and module members do not see a direct relationship.

Ii. The wording of the object

To solve the above shortcomings, you can write the module as an object, all module members are placed inside this object

var module1 = new Object ({
    _count:0,
    m1:function () {
        //...
    },
    m2:function () {
        //...
  
   }
});
  

The functions above M1 () and M2 () are encapsulated in the Module1 object. When used, the object's properties are invoked.

MODULE1.M1 ();

However, such writing exposes all module members and the internal state can be externally rewritten. For example, external code can directly change the value of an internal counter.

Module1._count = 5;

third, immediately execute function writing

You can achieve the purpose of not exposing private members by using the Execute function now (immediately-invoked function Expression,iife).

var Module1 = (function () {
    var _count = 0;
    var m1 = function () {
        //...
    };
    var m2 = function () {
//...
    };
    return {
        m1:m1,
        m2:m2
    };
}) ();

Using the above notation, the external code cannot read the internal _count variable

Console.info (Module1._count); Undefined

Module1 is the basic writing of JavaScript modules. Below, and then to the processing of this writing.

Four, enlarge the mode

If a module is large, it must be divided into several parts, or a module needs to inherit another module, then it is necessary to adopt the "magnification mode" (augmentation).

var Module1 = (function (mod) {
    mod.m3 = function () {
        //...
    };
    return mod;
}) (Module1);

The code above adds a new method M3 () to the Module1 module, and then returns the new Module1 module

v. Wide magnification mode (Loose augmentation)

In a browser environment, parts of a module are usually retrieved from the web, and sometimes it is not possible to know which part will be loaded first. If the previous section is written, the first part of the execution may load a nonexistent object, and the "wide magnification mode" is used.

var Module1 = (function (mod) {
    //...
    return mod;
}) (Window.module1 | | {});

In contrast to "zoom mode", the "wide magnification mode" is the "execute function now" argument can be an empty object.

vi. input Global Variables

Independence is an important feature of the module, it is best not to interact directly with other parts of the program.

In order to call global variables inside a module, you must explicitly enter the other variables into the module.

Specification of Modules

First think about why the module is important.

Because of the module, we can more easily use other people's code, want what function, loaded what module. However, this has a prerequisite, that is, we must write the same way the module, otherwise you have your writing, I have my writing, it is not a mess. This is even more important given the fact that JavaScript modules are not yet officially regulated.

Eight, Commonjs

2009, US programmer Ryan Dahl created the Node.js project, which uses JavaScript language for server-side programming. This sign "JavaScript modular Programming" is officially born. Because frankly speaking, in the browser environment, no module is not particularly big problem, after all, the complexity of the Web page program is limited, but on the server side, must have a module, and the operating system and other applications to interact, or simply can not program.

The modular system of Node.js is realized by reference to COMMONJS specification. In Commonjs, there is a global method require (), which is used to load modules. Assuming there is a mathematical module math.js, you can load it like this.

var math = require (' math ');

You can then invoke the method provided by the module:

var math = require (' math ');
Math.add (2,3); 5

Because this series is mainly for browser programming, does not involve node.js, so to Commonjs do not do more introduction. As long as we know here, require () is used to load the module.

Nine, browser environment

With the server-side module, it's natural for everyone to want the client module. And it's best to be compatible, a module that doesn't have to be modified, can run on both the server and the browser.

However, due to a significant limitation, the COMMONJS specification does not apply to the browser environment. or the previous section of the code, if you run in the browser, there will be a big problem, you can see it.

var math = require (' math ');
Math.add (2, 3);

The second line, Math.add (2, 3), runs after the first line require (' math '), so the math.js load must be completed. In other words, if the load time is very long, the entire application will stop there and so on.

This is not a problem for the server side, because all the modules are stored on the local hard drive, can be completed synchronously, waiting time is the hard disk read time. However, for browsers, this is a big problem, because the module is placed on the server side, waiting time depends on the speed of the network, may have to wait for a long time, the browser in the state of "suspended animation."

Therefore, the browser-side module cannot be "Synchronous load" (synchronous) and can only be used for "asynchronous loading" (asynchronous). This is the background of the birth of AMD specification.

10, AMD

AMD is the abbreviation for "Asynchronous module definition", meaning "asynchronous modular definition". It loads the module asynchronously, and the load of the module does not affect the operation of the statement behind it. All statements that rely on this module are defined in a callback function, and the callback function will not run until the load is complete.

AMD also uses the Require () statement to load modules, but unlike COMMONJS, it requires two parameters:

Require ([module], callback);

The first parameter [module], which is an array whose members are the modules to be loaded, and the second parameter callback, is the callback function after the success of the load. If you rewrite the previous code into AMD, this is the following:

Require ([' math '], function (math) {
    Math.add (2, 3);
});

Math.add () is not synchronized with the math module, and the browser does not feign death. So it's clear that AMD is better suited to the browser environment.

Currently, there are two JavaScript libraries that implement AMD specifications: Require.js and Curl.js. the use of Require.js

First, why use Require.js.

At the earliest, all of the JavaScript code was written in a file, and it was enough to load the file. Later, more and more code, a file is not enough, must be divided into multiple files, sequentially loaded. The following page code, I believe many people have seen.

<script src= "1.js" ></script>
<script src= "2.js" ></script>
<script src= "3.js" ></script>
<script src= "4.js" ></script>
<script src= "5.js" ></script>
<script src= "6.js" ></script>

This code loads multiple JS files sequentially.

There are a lot of drawbacks to this way of writing. First of all, when loading, the browser will stop the page rendering, the more loading files, the longer the page will lose the response time, and secondly, because the JS file dependencies, Therefore, we must strictly ensure the loading sequence (such as the above example of the 1.js to be in front of 2.js), the most dependent module must be put to the last load, when the dependency is very complex, code writing and maintenance will become difficult.

The birth of require.js is to solve these two problems:

(1) To realize the asynchronous loading of JS files to avoid web page loss of response;

(2) Management of the dependencies between modules, easy to write code and maintenance.

second, the loading of require.js

The first step in using Require.js is to go to the official website and download the latest version first.

After downloading, assume that it is placed under the JS subdirectory, you can load.

<script src= "Js/require.js" ></script>

One might think that loading the file could also cause the web to lose its response. There are two solutions, one is to put it at the bottom of the page load, the other is written as follows:

<script src= "js/require.js" defer async= "true" ></script>

The Async property indicates that the file needs to be loaded asynchronously to prevent the Web page from losing its response. IE does not support this property, only support defer, so put the defer also write.

After loading the require.js, the next step is to load our own code. Suppose our own code file is Main.js, also placed under the JS directory. Well, just write the following:

<script src= "Js/require.js" data-main= "Js/main" ></script>

The function of the Data-main property is to specify the main module of the Web page program. In the above example, is the JS directory below the main.js, this file will be the first to be require.js loaded. Because the require.js default file suffix name is js, you can abbreviate main.js to main

third, the main module of the formulation

The main.js in the previous section, which I call the "main module", means the entry code for the entire page. It's kind of like the C language main () function, where all the code starts running.

Here is a look, how to write Main.js.

If our code does not rely on any other modules, you can write JavaScript code directly.

Main.js
alert ("loaded successfully.") ");

But in this case, there is no need to use require.js. The real common scenario is that the main module relies on other modules, and the Require () function defined by the AMD specification is used.

Main.js
require ([' Modulea ', ' Moduleb ', ' Modulec '], function (Modulea, Moduleb, Modulec) {
    //some code HERE
  });

The Require () function accepts two parameters. The first argument is an array that represents the dependent module, and the example is [' Modulea ', ' Moduleb ',
' Modulec ', that is, the main module relies on these three modules; The second parameter is a callback function that will be invoked after the module specified by the current plane has been successfully loaded. The loaded modules are passed in as arguments to the function, which can be used inside the callback function.

Require () asynchronously loads Modulea,moduleb and Modulec, the browser does not lose its response, and its specified callback function, which runs only after the previous module has been successfully loaded, solves the dependency problem.

Next, let's look at a practical example.

Assuming that the main module relies on the three modules of jquery, underscore, and backbone, Main.js can write this:

Require ([' jquery ', ' underscore ', ' backbone '], function ($, _, Backbone) {
    //some code here
});

Require.js will load jquery, underscore, and backbone before running the callback function. The code for the main module is written in the callback function.

four, the module loading

In the last example of the previous section, the main module's dependency module is [' jquery ', ' underscore ', ' backbone ']. By default, Require.js assumes that these three modules are in the same directory as main.js, the file names are jquery.js,underscore.js and Backbone.js, and then are automatically loaded.

Using the Require.config () method, we can customize the loading behavior of the module. Require.config () is written on the head of the main module (main.js). The parameter is an object that specifies the load path of each module in the paths property of the object.

Require.config ({
    paths: {
        "jquery": "Jquery.min",
        "underscore": "Underscore.min",
        "backbone": " Backbone.min "
    }
});

The above code gives the file name of three modules, the path defaults to main.js in the same directory (JS subdirectory). If these modules are in other directories, such as the Js/lib directory, there are two ways to do it. One way is to specify the path.

Require.config ({
    paths: {
        "jquery": "Lib/jquery.min",
        "underscore": "Lib/underscore.min",
        " Backbone ":" Lib/backbone.min "
    }
});

The other is to change the base directory directly (BaseURL)

Require.config ({
    baseurl: "Js/lib",
    paths: {
        "jquery": "Jquery.min",
        "underscore": " Underscore.min ",
        " backbone ":" Backbone.min "
    }
});

If a module is on another host, you can also specify its URL directly, for example:

Require.config ({
    paths: {
        "jquery": "Https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min"
    ) }
});

Require.js requirements, each module is a separate JS file. This way, if you load multiple modules, you emit multiple HTTP requests that affect the speed at which the Web page loads. As a result, Require.js provides an optimization tool that, when deployed, can be used to merge multiple modules into a single file, reducing the number of HTTP requests.

Five, the AMD module's formulation

Require.js loaded modules, using AMD specifications. In other words, the module must be written in accordance with AMD rules.

Specifically, the module must be defined with a specific define () function. If a module does not rely on other modules, it can be directly defined in the Define () function.

Suppose you now have a math.js file that defines a math module. So, Math.js is going to write this:

Define (function () {
    var add = function (x,y) {return
        x+y;
    };
    return {
        add:add
    };
};

The loading method is as follows:

Main.js
require ([' math '], function (math) {
    alert (Math.add (1,1);
});

If the module also relies on other modules, then the first parameter of the Define () function must be an array that indicates the dependency of the module.

define ([' mylib '], function (mylib) {
    function foo () {
        mylib.dosomething ();
    }
    return {
        Foo:foo
    };
};

When the require () function loads the above module, the Mylib.js file is loaded first.

Vi. loading non-canonical modules

In theory, Require.js loaded modules must be in accordance with the AMD specification, using the Define () function defined modules. But in fact, although there are already some popular libraries (such as jquery) that conform to AMD specifications, more libraries do not match. So, is require.js able to load non-standard modules?

The answer is OK.

Such modules must first define some of their characteristics using the Require.config () method before they are loaded with require ().

For example, both the underscore and backbone libraries are not written using the AMD specification. If you want to load them, you must first define their characteristics.

Require.config {
    shim: {
        ' underscore ': {
            exports: ' _ '
        },
        ' backbone ': {
            deps: [' Underscore ', ' jquery '],
            exports: ' Backbone '
        }}}
);

Require.config () accepts a configuration object that, in addition to the previously mentioned paths attribute, has a shim property that is specifically configured to configure incompatible modules. Specifically, each module is to define (1) The exports value (the output variable name), indicating the name of the module outside the call;

For example, the jquery plug-in can be defined as:

Shim: {
    ' jquery.scroll ': {
        deps: [' jquery '],
        exports: ' JQuery.fn.scroll '
    }
}

Seven, Require.js plug-ins

Require.js also offers a range of plug-ins to implement certain features.

The Domready plug-in allows the callback function to run after the page DOM structure has completed loading.

Require ([' domready! '], function (DOC) {
    //called Once the DOM is ready
});

The text and image plug-ins are allowed to load require.js and picture files.

define ([
    ' Text!review.txt ',
    ' image!cat.jpg '
],function (review,cat) {
    console.log (review);
    Document.body.appendChild (cat);
};

Similar plug-ins include JSON and Mdown, which are used to load JSON files and markdown files.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.