Javascript模塊化開發-輕巧自制

1、前言

如今javascript的流行,前端的代碼愈來愈複雜,因此咱們須要軟件工程的思想來開發前端。模塊化是必不可少的,這樣不只可以提升代碼的可維護性、可擴展性以及魯棒性,更大的好處就是可以提高整個團隊的開發效率,也可以讓新進的程序員更快的接手工做。今天晚上根據前輩們的經驗,寫啦一個簡單的模塊定義的封裝組件,當是練手吧。不過感受仍是蠻好用的。javascript

2、學習模塊化前咱們應該先了解點什麼呢?

其實忽然就學習模塊化的javascript開發,那仍是比較丈二和尚,摸不着頭腦的。不過若是是作事後臺開發的程序員們,可能對於模塊化的開發思想並不陌生,由於後臺的這方面技術已經很熟悉了。那麼這裏我就分享一下前端javascript模塊化開發的學習。前端

1. 瞭解模塊化開發思想

若是有軟件工程背景,那麼這一思想就是你自身就應該掌握的。模塊(module)就是能夠組合、分解以及更換的單元,其實也知足組合大於繼承等這些帶來的好處吧。若是當作一個系統的話,咱們能夠從軟件體系結構來理解,模塊是較大系統中的獨立部件,功能、狀態與接口反映外部特性,邏輯反映的是內部特性。java

2. 瞭解前端模塊化開發帶來的好處

模塊化的開發模式爲前端帶來了新大陸,這點不得不認可,如今前端的愈加成熟,須要軟件工程的這種思想。
玉伯也發表過前端模塊化開發的價值git

3.瞭解目前技術,哪些和模塊化開發沾邊程序員

1) 開發功能模塊的時候,能夠採用Eva的解決方案(YUI3 + Minify)。github

2) 使用流行的javascript模塊加載框架:seajs。數組

3) 若是喜歡輕巧的東西,也能夠嘗試帶刀easy.js,不錯的一個模塊加載框架。數據結構

4) 也能夠嘗試支付寶的Alice,這是一款基於CMD規範的東東,首頁卻是挺小清新的。app

5) 現在比較火的NodeJS這是必需要了解和學習的。框架

好啦,瞭解完上面那些技術後,模塊化的前端模式應該很熟悉了,若是想紮實一下的話還能夠了解一下AMD、CMD規範,具體是什麼東西,google一下。接下來咱們就來構造一個簡單的模塊定義器吧,其實寫的時候還挺簡單的,不過主要是吸取思想,這樣學習技術纔不會跟不上時代。

3、輕巧範例

1. 模塊的數據結構(JSON表示)

module: {
    //模塊名稱
    moduleName: moduleName,
    //模塊依賴集合
    dependencies: dependencies,
    //模塊實例工廠
    factory: factory
}

2. 模塊定義

因此咱們最後可以造成模塊定義的代碼以下:

define: function ( moduleName, dependencies, factory ) {
    if( !modules[moduleName] ) {
        //模塊信息
        var module = {
            moduleName: moduleName,
            dependencies: dependencies,
            factory: factory
        };

        modules[moduleName] = module;
    }

    return modules[moduleName];
}

3. 模塊調用

這樣咱們就定義好了模塊,那麼咱們的入口在哪裏呢?咱們還須要定義一個use的方法,來成爲所謂的main,這樣綁定好了纔可以調用,如今想來程序也都是這樣的。下面這段代碼經過遞歸的產生模塊依賴的全部實例,可是這裏浪費了一部分instances數組的空間,有時間能夠再作哈優化。

use: function ( moduleName ) {
    //使用括號的方式訪問屬性,實現動態的賦值(詳情查閱「.」和[]的區別)
    var module = modules[moduleName];

    //產生單個實例
    if( !module.instance ) {
        var instances = [], 
            len = module.dependencies.length - 1;

            for( var i = 0; i <= len; i++ ) {
                var dependency = module.dependencies[i],
                    instance = dependency.instance;

                if( instance ) {
                    instances.push( instance );
                } else {
                    //遞歸,將每次產生的實例放入數組
                    instances.push( arguments.callee( dependency ) );
                }
            }
            //生成實例
            module.instance = module.factory.apply( null, instances );
    }

    return module.instance;
}

4. 完整代碼

最後我造成完整的本身的小庫。

(function ( window, undefined ) {
    var modules = {};
    var Sky = {
        //定義模塊的基本信息
        //1.模塊名稱,2.模塊的依賴,3.產生實例的工廠
        define: function ( moduleName, dependencies, factory ) {
            if( !modules[moduleName] ) {
                //模塊信息
                var module = {
                    moduleName: moduleName,
                    dependencies: dependencies,
                    factory: factory
                };

                modules[moduleName] = module;
            }

            return modules[moduleName];
        },
        //使用依賴
        use: function ( moduleName ) {
            var module = modules[moduleName];

            //產生單個實例
            if( !module.instance ) {
                var instances = [], 
                    len = module.dependencies.length - 1;

                for( var i = 0; i <= len; i++ ) {
                    var dependency = module.dependencies[i],
                        instance = dependency.instance;

                    if( instance ) {
                        instances.push( instance );
                    } else {
                        //遞歸,將每次產生的實例放入數組
                        instances.push( arguments.callee( dependency ) );
                    }
                }
                //生成實例
                module.instance = module.factory.apply( null, instances );
            }

            return module.instance;
        }
    };

    window.Sky = Sky || {};
})(window);

下面咱們來一個完整的例子來使用一下以上咱們構建的輕巧代碼。

Sky.define("constant.PI", [], function() {
    return 3.1415926;
});

Sky.define("shape.Circle", ["constant.PI"], function( pi ) {
    function Circle(r) {
        this.r = r || 0;
    };

    Circle.prototype.area = function() {
        return pi * this.r * this.r;
    };

    return Circle;
});

Sky.define("shape.Rectangle", [], function() {
    function Rectangle(width, height) {
        this.width = width || 0;
        this.height = height || 0;
    };

    Rectangle.prototype.area = function() {
        return this.width * this.height;
    };

    return Rectangle;
});

Sky.define("ShapeTypes", ["shape.Circle", "shape.Rectangle"], function( Circle, Rectangle ) {
    return {
        'CIRCLE': Circle,
        'RECTANGLE': Rectangle
    };
});

Sky.define("ShapeFactory", ["ShapeTypes"], function( ShapeTypes ) {
    return {
        getShape: function(type) {
            var shape;

            switch (type) {
            case 'CIRCLE':
                shape = new ShapeTypes[type](arguments[1]);
                break;
            case 'RECTANGLE':
                shape = new ShapeTypes[type](arguments[1], arguments[2]);
                break;
            }
            return shape;
        }
    };
});

var ShapeFactory = Sky.use("ShapeFactory");
console.log(ShapeFactory.getShape("CIRCLE").area());
console.log(ShapeFactory.getShape("RECTANGLE", 2, 3).area());

是否是感受js代碼變得更加清爽了?嘿嘿,上面的例子也是面向接口的,你們也能夠看看。

參考前輩:http://blog.jobbole.com/43649/

也許代碼有出入,有些地方前輩寫得不夠細心的我補上了一些,嘿嘿,可是思路是參考這位前輩的。

原文出自:http://www.60sky.com/

相關文章
相關標籤/搜索