requireJs原理分析

requireJs 原理探究以及demo實(shí)現(xiàn)

寫在前面:

大家在開發(fā)中丹莲,天天在使用requireJs,對(duì)于require的核心原理述寡,以及如何實(shí)現(xiàn)一個(gè)簡單的require肯定有所了解找岖,我們今天就聊聊require 。

在require中骑疆,根據(jù)AMD(Asynchronous Module Definition)的思想田篇,即異步模塊加載機(jī)制替废,其思想就是將代碼分為一個(gè)一個(gè)模塊分塊加載,來提高代碼的重用泊柬。

簡單流程概括

  1. 我們?cè)谑褂胷equireJs時(shí)椎镣,都是在頁面上只引入一個(gè)require.js,把data-main指向我們的main.js
  2. 運(yùn)行main.js時(shí)兽赁,執(zhí)行里面的require和define方法状答,requireJs會(huì)把這些依賴和回調(diào)方法都用一個(gè)數(shù)據(jù)結(jié)構(gòu)存起來
  3. 當(dāng)頁面加載時(shí),requireJs 會(huì)根據(jù)依賴預(yù)先先把需要的js通過document.createElement的方法引入dom中刀崖,這樣惊科,被引入dom的script便會(huì)執(zhí)行
  4. 依賴的js也是根據(jù)requireJs的規(guī)范來寫的,所以他們也會(huì)有define或者require方法亮钦,同樣類似第二步這樣循環(huán)向上查找依賴馆截,同樣會(huì)存起來
  5. 當(dāng)js需要用到依賴返回的結(jié)果,requireJs會(huì)把保存的方法拿出來并且運(yùn)行

測試代碼

下面是我自己寫的requirJs代碼的測試

index.html

<script src="./myrequire.js" type="text/javascript"></script>
<script type="text/javascript">
    require(['util', 'math', 'num'], function (util, math, num) {
        num = math.getRadom() + '_' + num;
        num = util.formatNum(num);
        console.log(num);
    });
</script>

util.js

define([], function () {
    return {
        formatNum: function (n) {
        if (n < 10) return '0' + n;
        return n;
        }
    };
});

math.js

define(['num'], function (num) {
  return {
    getRadom: function () {
      return parseInt(Math.random() * num);
    }
  };
});

num.js

define([], function () {
    return 10;
});

這些使用都很簡單,關(guān)鍵在研究myRequireJs的實(shí)現(xiàn)

開始研究

(function(){
    //將所有的依賴放在這里
    var moduleCache = {};

    var require = function(deps,callback) {
        var params = [];    // 這里放define后面的方法
        var depCount = 0;
        var i, len, isEmpty = false, modName;

        modName = document.currentScript && document.currentScript.id || 'REQUIRE_MAIN';

        if(deps.length) {
            for(i = 0, len = deps.length; i<len; i++) {
                (function(i){
                    depCount++;
                    loadMod(deps[i],function(param) {
                        params[i] = param;
                        depCount--;
                        if(depCount == 0) {
                            saveModule(modName,params,callback);
                        }
                    });
                })(i)
            }
        }else {
            isEmpty = true;
        }

        if(isEmpty) {
            setTimeout(function() {
                saveModule(modName,null,callback);
            }, 0);
        }
    }

    var _getPathUrl = function(modName) {
        var url = modName;
        if(url.indexOf('.js') == -1) url = url + '.js';
        return url;
    };

    var loadMod = function(modName,callback) {
        var url = _getPathUrl(modName), fs, mod;

        if(moduleCache[modName]) {
            mod = moduleCache[modName];
            if(mod.status == 'loaded') {
                setTimeout(callback(this.params), 0);
            } else {
                mod.onload.push(callback);
            }
        }else {
            mod = moduleCache[modName] = {
                modName: modName,
                status: 'loading',
                export: null,
                onload: [callback]
            };

            _script = document.createElement('script');
            _script.id = modName;
            _script.type = 'text/javascript';
            _script.charset = 'utf-8';
            _script.async = true;
            _script.src = url;

            fs = document.getElementsByTagName('script')[0];
            fs.parentNode.insertBefore(_script, fs);
        }
    };

    var saveModule = function(modName, params, callback) {
        var mod, fn;

        if(moduleCache.hasOwnProperty(modName)) {
            mod = moduleCache[modName];
            mod.status = 'loaded';

            mod.export = callback ? callback(params) : null;
            
            while(fn = mod.onload.shift()) {
                fn(mod.export);
            }
        } else {
            callback && callback.apply(window,params);
        }
    };

    window.require = require;
    window.define = require;

})(); 
代碼流程分析
image.png

注: 這里的require 和 define 都用的同一個(gè)通用方法蜂莉,都是通過里面 依賴參數(shù)判斷蜡娶,執(zhí)行同樣的類似方法來實(shí)現(xiàn)這個(gè)效果

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市映穗,隨后出現(xiàn)的幾起案子窖张,更是在濱河造成了極大的恐慌,老刑警劉巖蚁滋,帶你破解...
    沈念sama閱讀 210,914評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件宿接,死亡現(xiàn)場離奇詭異,居然都是意外死亡枢赔,警方通過查閱死者的電腦和手機(jī)澄阳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來踏拜,“玉大人碎赢,你說我怎么就攤上這事∷俟#” “怎么了肮塞?”我有些...
    開封第一講書人閱讀 156,531評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長姻锁。 經(jīng)常有香客問我枕赵,道長,這世上最難降的妖魔是什么位隶? 我笑而不...
    開封第一講書人閱讀 56,309評(píng)論 1 282
  • 正文 為了忘掉前任拷窜,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘篮昧。我一直安慰自己赋荆,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評(píng)論 5 384
  • 文/花漫 我一把揭開白布懊昨。 她就那樣靜靜地躺著窄潭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪酵颁。 梳的紋絲不亂的頭發(fā)上嫉你,一...
    開封第一講書人閱讀 49,730評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音躏惋,去河邊找鬼幽污。 笑死,一個(gè)胖子當(dāng)著我的面吹牛其掂,可吹牛的內(nèi)容都是我干的油挥。 我是一名探鬼主播,決...
    沈念sama閱讀 38,882評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼款熬,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了攘乒?” 一聲冷哼從身側(cè)響起贤牛,我...
    開封第一講書人閱讀 37,643評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎则酝,沒想到半個(gè)月后殉簸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,095評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡沽讹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評(píng)論 2 325
  • 正文 我和宋清朗相戀三年般卑,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片爽雄。...
    茶點(diǎn)故事閱讀 38,566評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蝠检,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出挚瘟,到底是詐尸還是另有隱情叹谁,我是刑警寧澤,帶...
    沈念sama閱讀 34,253評(píng)論 4 328
  • 正文 年R本政府宣布乘盖,位于F島的核電站焰檩,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏订框。R本人自食惡果不足惜析苫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧衩侥,春花似錦国旷、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至璧榄,卻和暖如春特漩,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背骨杂。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評(píng)論 1 264
  • 我被黑心中介騙來泰國打工涂身, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人搓蚪。 一個(gè)月前我還...
    沈念sama閱讀 46,248評(píng)論 2 360
  • 正文 我出身青樓蛤售,卻偏偏與公主長得像,于是被迫代替她去往敵國和親妒潭。 傳聞我的和親對(duì)象是個(gè)殘疾皇子悴能,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容