深入理解javascript系列(十):模組化與閉包

Panthon發表於2019-03-03

如果想在所有的地方都能訪問同一個變數,那麼應該怎麼辦呢?

在實踐中這種場景很多,比如全域性的狀態管理。

但前面我們介紹過,在實際開發中,不要輕易使用全域性變數,那又該怎麼辦呢?模組化的思維能夠幫助我們解決這個問題。

模組化開發是目前最流行,也是必須要掌握的一種開發思路。而模組化其實是建立在單例模式基礎之上的,因此模組化開發和閉包息息相關。

目前流行的模組化開發思路,無論是require,還是ES6的modules,雖然實現方式不同,但是核心思路一樣。因此為了方便大家理解模組化的思維,這裡就以建立在函式自執行基礎上的單例模式為例,一起來感受一下模組化開發的魅力。

第一,請記住:每一個單例就是一個模組。

其實,你也知道,每一個檔案也是一個模組。而這裡把每一個單例模式假想成一個單獨的檔案即可。定義一個模組,而變數名就是模組名。

var module_test = (function() {
    
})();複製程式碼

第二,每一個模組要想與其他模組互動,則必須有獲取其它模組的能力,例如requirejs中的require與ES6modules中的import。

//require
var $ = require(`jquery`);

//es6 modules
import $ from `jquery`;複製程式碼

第三,每一個模組都應該有對外的介面,以保證與其他模組互動的能力。這裡直接使用return返回一個字面量物件的方式來對外提供介面。(你可以回顧一下現在那些模組的匯出是多麼便捷)

var module_test = (function() {
      ...
      
      return {
          testfn1: function() {},
          testfn2: function() {}
      }  
})();複製程式碼

現在我們結合一個簡單的案例來走一遍模組化開發的流程。這個例子想要實現的功能是每個一秒,body的背景色就隨著一個數字的遞增在固定的三種顏色之間切換。

(1)首先建立一個專門用來管理全域性狀態的模組。這個模組中有一個私有變數儲存了所有的狀態值,並對外提供了訪問與設定這個私有變數的方法,程式碼如下:

var module_status = (function() {
    var status = {
        number: 0,
        color: null
    }

    var get = function(prop) {
        return status[prop];
    }
    
    var set = function(prop,value) {
        status[prop] = value;
    }

    return {
        get,
        set
    }
})();複製程式碼

(2)在來建立一個模組,這個模組專門負責body背景顏色的改變。

var module_color = (function() {
    
    //假裝用這種方式執行第二步引入模組
    //類似 import state from `module_status`;

    var state = module_status;
    var colors = [`yellow`,`#ccc`,`red`];

    function render() {
        var color = colors[state.get(`number`) % 3];
        document.body.style.backgroundColor = color;
    }

    return {
        render
    }
})();複製程式碼

在這個模組,引入了狀態管理的模組,並且將顏色的管理與改變方式都定義在該模組中,因此在使用時我們只需呼叫render方法就可以了。

接下來我們還需要建立另外一個模組來負責顯示當前的number的值,用於參考對比。

var module_context = (function() {
    var state = module_status;

    function renderNumber() {
        document.body.innerHTML = `now number is` + state.get(`number`);
    }

    return {
        renderNumber
    }
})()複製程式碼

這些功能模組都建立完畢後,最後我們只需建立一個主模組即可。這個主模組的目的就是藉助功能模組,來實現我們想要的效果。

var module_main = (function() {
    var state = module_status;
    var color = module_color;
    var context = module_context;

    setInterval(function() {
        var newNumber = state.get(`number`) + 1;
        state.set(`number`,newNumber);

        color.render();
        context.renderNumber();
    },1000)
})();複製程式碼

好了,整一個模組化就完成了。你可以將整段程式碼插入到一個HTML檔案script標籤下即可看到展示效果。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>change yourself</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
<script>
    var module_status = (function() {
        var status = {
            number: 0,
            color: null
        }

        var get = function(prop) {
            return status[prop];
        }

        var set = function(prop,value) {
            status[prop] = value;
        }

        return {
            get,
            set
        }
    })();

    var module_color = (function() {

        //假裝用這種方式執行第二步引入模組
        //類似 import state from `module_status`;

        var state = module_status;
        var colors = [`yellow`,`#ccc`,`red`];

        function render() {
            var color = colors[state.get(`number`) % 3];
            document.body.style.backgroundColor = color;
        }

        return {
            render
        }
    })();

    var module_context = (function() {
        var state = module_status;

        function renderNumber() {
            document.body.innerHTML = `now number is` + state.get(`number`);
        }

        return {
            renderNumber
        }
    })();

    var module_main = (function() {
        var state = module_status;
        var color = module_color;
        var context = module_context;

        setInterval(function() {
            var newNumber = state.get(`number`) + 1;
            state.set(`number`,newNumber);

            color.render();
            context.renderNumber();
        },1000)
    })();
</script>複製程式碼

執行以上完整程式碼,就可以看到如果效果啦

深入理解javascript系列(十):模組化與閉包

當然它是每個一秒變一次的….

這些都是我以往的學習筆記。如果您看到此筆記,希望您能指出我的錯誤。有這麼一個群,裡面的小夥伴互相監督,堅持每天輸出自己的學習心得,不輸出就出局。希望您能加入,我們一起終身學習。歡迎新增我的個人微訊號:Pan1005919589

相關文章