Home > Web Front-end > JS Tutorial > How to implement modularization of JS code

How to implement modularization of JS code

巴扎黑
Release: 2017-05-27 10:53:20
Original
1714 people have browsed it

Why should we use the module mode?

Because variables and functions declared in the global scope automatically become properties of the global object Window, which often leads to naming conflicts. , will also lead to some very important maintainability problems. The more global variables, the greater the probability of introducing bugs! So we should use global variables as little as possible. One of the purposes of modularization is to solve this problem. !

Zero global variable mode

This mode has fewer application scenarios and uses an IIFE (immediately executed anonymous function), wrap all code, so that all variables and functions are hidden inside the function and will not pollute the global world.

Usage scenarios:

    • When the code is not dependent on other code;

    • When there is no need to continuously expand or modify the code at runtime;

    • When When the code is shorter and does not need to interact with other codes;

  Single global variable mode

Basic definition

Single global variable mode means creating only one global variable (or creating as few global variables as possible variable), and the name of the global variable must be unique and will not conflict with current or future built-in APIs. All functional codes must be mounted on this global variable.

It has been widely used in various popular class libraries, such as:

  1. YUI defines a unique The YUI global object

  2. JQuery defines two global objects, $ and JQuery

  3. Dojo defines a dojo global object

  4. Closure defines a goog global object

Example:

var Mymodule= {}; 
 
Mymodule.Book = function(){...}; 
Mymodule.Book.prototype.getName = function(){....}; 
 
Mymodule.Car = function(){...}; 
Mymodule.Car.prototype.getWheels = function(){....};
Copy after login

 Definition of a module

A module is a general functional fragment that does not create new global variables or namespaces. Instead, all code is stored in a single function. This module can be represented by a name, and this module can also depend on other modules. .

function CoolModule(){ 
        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 = CoolModule(); 
foo.doSomething(); //cool 
foo.doAnother(); //1!2!3
Copy after login

CoolModule here It is a module, but it is just a function. The CoolModule function is called here to create an instance foo of the module. At this time, a closure is formed (because CoolModule returns an object, one of which attributes refers to the internal function). The module CoolModule returns The object is the public API of the module (you can also directly return an internal function)

Therefore, the module mode needs to meet two necessary conditions:

  1. There must be an external closed function, and the function must be called at least once (each call will create a new module instance), such as CoolModule

  2. The closed function must have at least one internal function returned, so that the internal function can form a closure in the private scope and can access or modify the private state

Implementation of singleton module pattern:

var foo = ( function CoolModule(){ 
        ...//代码同上例 
})(); 
foo.doSomething(); 
foo.doAnother();
Copy after login

You can also retain internal references to public API objects inside the module, so that the module instance can be modified internally , including adding and deleting methods and attributes

function CoolModule(){ 
    var something = 'cool'; 
    var another = [1,2,3]; 
    function change() { 
        pubicAPI.doSomething = doAnother; 
    } 
    function doSomething(){ 
        console.log( something); 
    } 
    function doAnother(){ 
        console.log(another.join('!')); 
    } 
    var pubicAPI = { 
        change: change, 
        doSomething: doSomething 
    }; 
    return pubicAPI; 
} 
var foo = CoolModule(); 
foo.doSomething(); //cool 
foo.change(); 
foo.doSomething(); //1!2!3 
var foo1 = CoolModule(); 
foo1.doSomething(); //cool
Copy after login

Modern module mechanism

The namespace is simply passed in Add attributes to global variables to represent functional groupings.

Grouping different functions according to namespaces can keep your single global variables organized and allow team members to know in which section new functions should be defined. Or go to which section to find existing functions.

  例如:定义一个全局变量Y,Y.DOM下的所有方法都是和操作DOM相关的,Y.Event下的所有方法都是和事件相关的。

  1.   常见的用法是为每一个单独的JS文件创建一个新的全局变量来声明自己的命名空间;

  2.   每个文件都需要给一个命名空间挂载功能;这时就需要首先保证该命名空间是已经存在的,可以在单全局变量中定义一个方法来处理该任务:该方法在创建新的命名空间时不会对已有的命名空间造成破坏,使用命名空间时也不需要再去判断它是否存在。

var MyGolbal = { 
    namespace: function (ns) { 
        var parts = ns.split('.'), 
            obj = this, 
            i, len = parts.length; 
        for(i=0;i<len;i++){ 
            if(!obj[parts[i]]){ 
                obj[parts[i]] = {} 
            } 
            obj = obj[parts[i]]; 
        } 
        return obj; 
    } 
}; 
MyGolbal.namespace(&#39;Book&#39;); //创建Book 
MyGolbal.Book; //读取 
MyGolbal.namespace(&#39;Car&#39;).prototype.getWheel = function(){...}
Copy after login

  大多数模块依赖加载器或管理器,本质上都是将这种模块定义封装进一个友好的API

var MyModules = (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[name]; 
    } 
    return { 
        define: define, 
        get: get 
    }; 
})();
Copy after login

  以上代码的核心是modules[name] = impl.apply(impl,deps);,为了模块的定义引入了包装函数(可以传入任何依赖),并且将模块的API存储在一个根据名字来管理的模块列表modules对象中;

  使用模块管理器MyModules来管理模块:

MyModules.define(&#39;bar&#39;,[],function () { 
    function hello(who) { 
        return &#39;let me introduce: &#39;+who; 
    } 
    return{ 
        hello: hello 
    }; 
}); 
MyModules.define(&#39;foo&#39;,[&#39;bar&#39;],function (bar) { 
    var hungry = &#39;hippo&#39;; 
    function awesome() { 
        console.log(bar.hello(hungry).toUpperCase()); 
    } 
    return { 
        awesome: awesome 
    }; 
}); 
var foo = MyModules.get(&#39;foo&#39;); 
foo.awesome();//LET ME INTRODUCE: HIPPO
Copy after login

  异步模块定义(AMD):

define(&#39;my-books&#39;, [&#39;dependency1&#39;,&#39;dependency2&#39;],  
    function (dependency1, dependency2) { 
        var Books = {}; 
        Books.author = {author: &#39;Mr.zakas&#39;}; 
        return Books; //返回公共接口API 
    } 
);
Copy after login

  通过调用全局函数define(),并给它传入模块名字、依赖列表、一个工厂方法,依赖列表加载完成后执行这个工厂方法。AMD模块模式中,每一个依赖都会对应到独立的参数传入到工厂方法里,即每个被命名的依赖最后都会创建一个对象被传入到工厂方法内。模块可以是匿名的(即可以省略第一个参数),因为模块加载器可以根据JavaScript文件名来当做模块名字。要使用AMD模块,需要通过使用与AMD模块兼容的模块加载器,如RequireJS、Dojo来加载AMD模块

requre([&#39;my-books&#39;] , function(books){ 
            books.author; 
            ... 
   } 
)
Copy after login

  以上所说的模块都是是基于函数的模块,它并不是一个能被稳定识别的模式(编译器无法识别),它们的API语义只是在运行时才会被考虑进来。因此可以在运行时修改一个模块的API

  未来的模块机制

  ES6为模块增加了一级语法支持,每个模块都可以导入其它模块或模块的特定API成员,同样也可以导出自己的API成员;ES6的模块没有‘行内’格式,必须被定义在独立的文件中(一个文件一个模块)ES6的模块API更加稳定,由于编译器可以识别,在编译时就检查对导入的API成员的引用是否真实存在。若不存在,则编译器会在运行时就抛出‘早期’错误,而不会像往常一样在运行期采用动态的解决方案;

  bar.js

function hello(who) { 
    return &#39;let me introduce: &#39;+who; 
} 
export hello; //导出API: hello
Copy after login

  foo.js

//导入bar模块的hello() 
import hello from &#39;bar&#39;; 
 
var hungry = &#39;hippo&#39;; 
function awesome() { 
    console.log(hello(hungry).toUpperCase()); 
} 
export awesome;//导出API: awesome
Copy after login

  baz.js

//完整导入foo和bar模块 
module foo from &#39;foo&#39;; 
module bar from &#39;bar&#39;; 
foo.awesome();
Copy after login
  1.   import可以将一个模块中的一个或多个API导入到当前作用域中,并分别绑定在一个变量上;

  2.   module会将整个模块的API导入并绑定到一个变量上;

  3.   export会将当前模块的一个标识符(变量、函数)导出为公共API;

  4.   模块文件中的内容会被当做好像包含在作用域闭包中一样来处理,就和函数闭包模块一样;

The above is the detailed content of How to implement modularization of JS code. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:php.cn
Statement of this Website
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
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template