js 簡易模塊加載器 示例分析

前端模塊化

關注前端技術發展的各位親們,確定對模塊化開發這個名詞不陌生。隨着前端工程愈來愈複雜,代碼愈來愈多,模塊化成了必不可免的趨勢。javascript

各類標準

因爲javascript自己並無制定相關標準(固然es6已經有了import和export),因此在模塊化方面誕生了各類不一樣的規範。主要有AMD規範(隨requirejs誕生而普及),CMD規範(隨seajs的出現而普及),commonjs(主要用於node,並不適合前端)。至於以上幾種規範的異同,無恥的我在這裏就很少費口水了,請還不瞭解的親們自行去找google爸爸。前端

簡易模塊加載器示例

G點來了!
接下來咱們先來看一段建議模塊加載器的示例代碼:java

let Module = (() => {
    let module_list = {};
    function define(name,rely,callback){
        if (module_list[name]){
            console.log("The module have already existed!")
        }else{
            for(let i = 0;i < rely.length;i++){
                rely[i] = module_list[rely[i]];
            }
            module_list[name] = callback.apply(callback,rely);
        }
    }

    function require(name){
        if (module_list[name]){
            return module_list[name]
        }else{
            console.log("There is no such module!")
        }
    }

    let api = {
        "define":define,
        "require":require
    };
    return api;
})();

以上是加載器的實現,再來看看如何使用吧:node

Module.define("test",[],()=>{
    function sayHello(name){
        return name+",你好啊";
    }
    return {
        "sayHello":sayHello
    }
})

Module.define("haha",[],()=>{
    function gotoHZ(name){
        return name+"要去杭州玩了";
    }
    return {
        "gotoHZ":gotoHZ
    }
})
Module.define("my_module",["test","haha"],(test,haha)=>{
    let name = "andrew";
    function sayHello2() {
        let str = test.sayHello(name);
        console.log(haha.gotoHZ("章煒"))
        str = str + ",今每天氣不錯噢";
        return str;
    }

    return {
        "sayHello2":sayHello2
    }
})

console.log(Module.require('my_module').sayHello2())
console.log(Module.require('test').sayHello("steve"))

在以上代碼中,咱們定義了三個模塊,分別名爲test,haha,my_module。看到這裏的你,若是js基礎很差,多是一臉懵逼,腦子繞暈...先不急,讓咱們來看看運行的結果:
模塊加載器es6

結果很簡單,打印了一些咱們想要的信息。api

代碼分析

接下來咱們詳細來解析一下代碼原理。
加載器中的幾個重點,閉包

  1. module_listapp

    module_list是一個對象,用於存儲定義的模塊,以模塊名:callback這樣
    的鍵值對的形式存儲;模塊化

  2. define函數函數

    而後咱們定義了一個define函數,其三個參數分別爲模塊名、此模塊依賴列表、此模塊回調函數,當咱們調用define函數時,首先先去檢查module_list
    象中是否已經有同名模塊,若是有,直接告訴用戶該模塊名字已被使用,若是沒有,咱們循環依賴列表rely,循環中的操做用於將依賴列表從名稱列表轉換爲真正的模塊列表,而後利用apply函數,將其逐個傳入到定義好的callback函數中。

  3. require函數
    因爲咱們的module_list存在於內部做用域,保證了模塊的私密性,外部並不能
    直接操做模塊列表去讀取模塊,所以咱們定義了一個require函數,利用閉包來讀取操做相應模塊

  4. 實例解析

    Module.define("my_module",["test","haha"],(test,haha)=>{
    let name = "andrew";
    function sayHello2() {
        let str = test.sayHello(name);
        console.log(haha.gotoHZ("章煒"))
        str = str + ",今每天氣不錯噢";
        return str;
    }
    
    return {
        "sayHello2":sayHello2
    }
    })

這裏咱們定義了my_module模塊,它依賴的模塊有testhaha兩個模塊,而在回調函數中,咱們將這兩個模塊傳入,能夠看到咱們能調用test模塊的sayHello方法,能夠調用haha模塊的gotoHZ方法,至此,一個簡單的模塊加載器就實現了。

結語

這個簡單的模塊加載器只是很簡化的介紹了模塊加載器實現的基本原理,成熟的模塊加載器固然是要複雜得多,可是原理了解了,纔是最重要,不是嘛~

相關文章
相關標籤/搜索