JavaScript模块化笔记摘抄

在可扩展JavaScript的世界里,如果说一个应用程序是模块化(Modular)的,那么通常意味着它是由一系列存储于模块中的高度解耦、不同的功能片段组成的。

AMD

异步模块定义(AMD)的整体目标是提供模块化的JavaScript解决方案,以便开发人员使用。AMD模块格式本身就是对定义模块的建议,其模块和依赖都可以进行异步加载。

AMD的两个关键概念

  • 用于模块定义的define方法
  • 用于处理依赖加载的require方法
define方法
define(
    module_id, /*可选*/
    [dependencies], /*可选*/
    definition function /*实例化模块或对象的函数*/
);
  • module\_id 是一个可选参数,它通常只在非AMD连接工具时才需要。当遗漏这个参数时,我们称这个模块为匿名的(anonymous)。可以将 module\_id 想象成类似文件路径的概念。
  • dependencies 参数表示我们定义的模块所需的依赖数组。
  • definition function / factory function 用于执行实例化模块的函数。
define()演示
define(
    "myModule", // 定义module_id(myModule)
    ["foo", "bar"], // 依赖[foo, bar]两个模块
    function (foo, bar) {
        
        // 在这里创建你的模块
        var myModule = {
            dostuff: function(){
                // Do somthing
            }
        }

        // 返回定义的模块输出(例如:要暴露的内容)
        return myModule;
});

Or

define(
    "myModule", 
    ["math", "graph"], // 依赖[math, graph]两个模块
    function (math, graph) {
        
        // 和AMD不大一样,通过 特定的语法以不同的形式定义模块
        return {
            plot: function (x, y) {
                return graph.drawPie(math.randomGrid(x, y));
            }
        };
});
require方法
require(["foo", "bar"], function (foo, bar) {
    // 剩余代码
    foo.dosomthing();
})
require()演示

动态加载依赖

define(function (require) {
    var isReady = false, foobar;

    // 模块内部的require定义
    require(["foo", "bar"], function (foo, bar) {
        isReady = true;
        foobar = foo() + bar();
    });

    // 返回一个模块
    return {
        isReady: isReady;
        foobar: foobar;
    };
});

使用RequireJS加载AMD模块

require(["app/myModule"], 
    function(myModule){
        // 开始主模块,顺序加载其他模块
        var module = new myModule();
        module.doStaff();
});

使用jQuery的AMD模块

define(["js/jquery.js", "js/jquery.color.js", "js/underscore.js"],
    function ($, colorPlugin, _) {
        // 传入了jQuery,color插件和Underscore,三者在全局作用域都不可访问,但却可以在内部轻松访问
        // 随机产生颜色数字,选择数组的第一项进行操作
        var shuffleColor = _.first(_.shuffle("#666", "#333", "#111"));
        
        // 将页面上所有带有class为item的元素都进行背景颜色的改变动画操作,使用shuffleColor这个颜色
        $(".item").animate({
            "background": shuffleColor
        });

        // 返回的值可以用于其他模块
        return {};

});
命名的AMD提供了一种安全方式,可以安全稳健地用于大多数用例。
// 在document对象中,负责各个jQuery全局实例,便于测试.noConflict

var jQuery = this.jQuery || "jQuery";
$ = this.$ || "$";

originaljQuery = jQuery,
original$ = $;
define(["jquery"], function ($) {
    $(".item").css("background", "green");
    return function(){};
});

CommonJS

CommonJS 模块建议指定一个简单的API来声明在浏览器外部工作的模块(如在服务器上)。它是JavaScript中可复用的部分,导出特定对象,一边可以用于任何依赖代码。与AMD不同,在这种模块周围通常是没有函数封装器的(所以我们在这里看不到define)。

CommonJS的两个主要部分

  • 自由变量 exports , 它包含了一个模块希望其他模块能够使用的的对象。
  • require 函数, 模块可以使用该函数导入(import)、其他模块的导出(exports)。
require()和导出
// package/lib 是我们需要的一个依赖
var lib = require("package/lib");

// 模块行为
function foo(){
    lib.log("hello world");
}

//导出(暴露)foo给其他模块
exports.foo = foo;
CommonJS演示AMD等效代码
define(function(require){
    var lib = require("package/lib");

    // 模块行为
    function foo(){
        lib.log("Hello World");
    }

    // 导出(暴露)foo给其他模块
    return {
        foobar: foo
    };
})

CommonJS使用多个依赖

app.js
var modA = require("./foo");
var modB = require("./bar");

exports.app = function(){
    console.log("I'm am application");
}

exports.foo = function(){
    return modA.helloWorld();
}
bar.js
exposrts.name = "bar";
foo.js
require("./bar");

exports.helloWorld = function(){
    return "Hello World!!!"
}

AMD 和 CommonJS 的比较

AMD和CommonJS都是有效的模块格式,有不同的最终目标。

AMD

AMD 采用浏览器优先的开发方法,选择一部行为和简化的向后兼容性,但是它没有任何文件I/O概念。它支持对象、函数、构造函数、字符串、JSON以及很多其他类型的模块,在浏览器中原生运行,使用非常灵活。

CommonJS

CommonJS 采用服务器优先方法,假定同步行为,没有全局概念这个包袱,并试图迎合未来技术(在服务器上)。由于CommonJS支持非包装模块,这样可以摆脱AMD强制执行的define()包装器。但CommonJS模块仅将对象作为模块给予支持。

    —

END.