Javascript AMD學習

海鳥發表於2014-08-24

我們知道在其它程式語言中, 都有包(命令空間)的概念, 幫助我們更好的管理程式碼結構. 如java中的package, python中的module. 但是在js語言中, 在一個頁面執行環境內, 所有引入的外部的js檔案都會在同一個global上下文中執行, 做不到幾點: 不能動態載入我們只需要的模組; 沒有package的概念, 程式碼管理混亂. 雖然語言這一層次做不到, 但是從上面一層可以做到, 所以就有了AMD規範標準: Asynchronous module definition.

假設我們現在的檔案目錄如下:

我們在amd.html裡定義兩個核心函式: require和define

var modules = {};
    var defQ = [];

    function onLoad(script, module){
        script.addEventListener("load", function(){
            var defFactory = defQ.shift();
            module.def = defFactory;
            module.executed = 1;
        }, false);
    }

    function require(deps, callback){
        for(var i = 0; i < deps.length; i++){
            var module = {
                executed: 0,
                url: deps[i]
            };

            var script = document.createElement("script");
            script.type = "text/javascript";
            script.src = deps[i];
            script.charset = "utf-8";
            onLoad(script, module);

            modules[deps[i]] = module;

            document.body.appendChild(script);
        }

        var id = setInterval(function(){
            var args = [];
            for(var i = 0; i < deps.length; i++){
                var dep = modules[deps[i]];
                if(!dep.executed){
                    return;
                }else{
                    args.push(dep.def());
                }
            }

            clearInterval(id);
            callback.apply(null, args);
        }, 1000);




    };


    function define(factory){
        defQ.push(factory);
    }

 現在我們定義了兩個js模組檔案: my/a.js和my/b.js, 分別如下:

// my/a.js
define(function(){
    return {
        name: "tony"
    }
});
// my/b.js
define(function(){
    return {
        name: "lily"
    }
});

現在我們可以在其它任何一個地方來動態載入這兩個模組檔案了, 使用如下:

require(['js/my/a.js', 'js/my/b.js'], function(a, b){
        console.debug(a.name + " " + b.name);
    });

上面的require和define只是一個簡單的AMD思路, 實際中複雜得多, 如要處理迴圈信賴等等複雜的情況.

 

相關文章