成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

簡(jiǎn)單實(shí)現(xiàn) JavaScript 模塊加載

tigerZH / 1869人閱讀

摘要:語(yǔ)言官方未實(shí)現(xiàn)命名空間,我們定義一個(gè)函數(shù)以實(shí)現(xiàn)命名空間。函數(shù)的使用如我們可以這樣實(shí)現(xiàn)對(duì)象保存著所有已加載的模塊每一個(gè)模塊實(shí)例都有屬性作為時(shí)查找的標(biāo)識(shí)符,屬性作為對(duì)外暴露的對(duì)象,屬性表示是否加載完。將函數(shù)傳入,來(lái)支持模塊內(nèi)引用其他模塊。

JavaScript語(yǔ)言官方未實(shí)現(xiàn)命名空間,我們定義一個(gè)define函數(shù)以實(shí)現(xiàn)命名空間。define函數(shù)的使用如:

define(function(exports, module, require) {
    const $ = require("http://path/to/defined-jquery");
    $(function(){
        // dom ready!!!
    });
});

我們可以這樣實(shí)現(xiàn):

(function(global) {
    "use strict";
    var errMsg = Math.random().toString(32).substr(2);
    // rootModule 對(duì)象保存著所有已加載的模塊
    var rootModule = {};

    // 每一個(gè)模塊實(shí)例都有id屬性作為require時(shí)查找的標(biāo)識(shí)符,
    // exports屬性作為對(duì)外暴露的對(duì)象,loaded屬性表示是否加載完。
    function ModuleCtor(id) {
        if (!this || this.__proto__ !== ModuleCtor.prototype) {
            return new ModuleCtor(id);
        }
        this.id = id;
        this.exports = {};
        this.loaded = !1;
    }

    function define(id, fn) {
        // 手動(dòng)賦值模塊id,兼容一個(gè)script里有多個(gè)define。
        if (typeof id === "function") {
            fn = id;
            id = document.currentScript
                ? document.currentScript.src
                : Math.random()
                      .toString(32)
                      .substr(2);
        }
        if (typeof id !== "string") {
            id = "" + id;
        }
        var module = ModuleCtor(id);
        exec();
        function __require__(src) {
            // 如果依賴已經(jīng)加載過(guò)直接返回module.exports,
            // 如果沒(méi)有加載過(guò)則通過(guò)jsonp加載,并且拋出一個(gè)異常來(lái)打斷原函數(shù)執(zhí)行,在子模塊加載完畢后重新執(zhí)行原函數(shù)模擬異步代碼阻塞同步執(zhí)行。
            if (rootModule[src] && rootModule[src].__proto__ === ModuleCtor.prototype) {
                return rootModule[src].exports;
            }
            loadScript(src, function() {
                exec();
            });
            throw new Error(errMsg);
        }
        function exec() {
            // 將__require__函數(shù)傳入fn,來(lái)支持模塊內(nèi)引用其他模塊。
            try {
                fn.call(module.exports, module.exports, module, __require__);
                module.loaded = !0;
                rootModule[id] = module;
            } catch (err) {
                if (err.message !== errMsg) {
                    throw err;
                }
            }
        }
    }

    function loadScript(src, callback) {
        var script = document.createElement("script");
        script.src = src;
        script.onload = function() {
            callback && callback(src);
        };
        document.body.appendChild(script);
        return script;
    }
    // 暴露define給全局
    global.define = define;
})(window);

這個(gè)模塊加載的實(shí)現(xiàn)有很多不足,如果模塊內(nèi)有很多require時(shí)會(huì)被執(zhí)行很多次,所以最好子模塊內(nèi)都是函數(shù)不要有自己的狀態(tài)。seajs的依賴解決方法是,調(diào)用函數(shù)的toString方法來(lái)獲得函數(shù)字面量,然后在parse出模塊依賴,先加載依賴,每一個(gè)依賴加載完成后都emit一個(gè)事件,當(dāng)所有依賴都加載完畢后,才執(zhí)行factory函數(shù),factory函數(shù)只執(zhí)行一次,但是模塊加載的順序和require的順序基本沒(méi)有關(guān)系(并發(fā)請(qǐng)求,誰(shuí)都有可能先到)。

======= 一本正經(jīng)的分割線 ======
順便吐槽一下seajs,由于某種原因,我再8102年見(jiàn)到了seajs而我在3000年前沒(méi)用過(guò)。文檔始終沒(méi)有交代require("caonima");是如何打斷函數(shù)執(zhí)行的??戳嗽创a發(fā)現(xiàn)是用了Function.prototype.toString方法,然后分析依賴并發(fā)加載(require函數(shù)是沒(méi)有順序之分的)??丛创a前,我自己為了模擬該行為,通過(guò)拋出異常再反復(fù)的重新執(zhí)行也實(shí)現(xiàn)了一個(gè)文件加載,而且我這個(gè)更賤的貨還是真的同步引入依賴,更加cmd一些。

附 Webpack 模塊加載原理:

(function(modulesArr) {
    var rootModule = {};
    function __require__(id) {
        if (rootModule[id]) {
            return rootModule[id].exports;
        }
        var currentModule = modulesArr[id];
        var module = {
            id,
            exports: {}
        };
        currentModule.call(module.exports, module.exports, module, __require__);
        currentModule[id] = module;
        return module.exports;
    }
    return __require__(0);
})([
    function(exports, module, require) {
        var m1 = require(1);
        console.log(m1);
    },
    function(exports, module, require) {
        exports.msg = "Hello World";
        var m2 = require(2);
        m2();
    },
    function(exports, module, require) {
        module.exports = function() {
            var str = "Hello World";
            console.log(str);
            return str;
        };
    }
]);

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/95627.html

相關(guān)文章

  • 【Node】前后端模塊規(guī)范與模塊加載原理

    摘要:例如指定一些依賴到模塊中實(shí)現(xiàn)規(guī)范的模塊化,感興趣的可以查看的文檔。 CommonJS 定義了 module、exports 和 require 模塊規(guī)范,Node.js 為了實(shí)現(xiàn)這個(gè)簡(jiǎn)單的標(biāo)準(zhǔn),從底層 C/C++ 內(nèi)建模塊到 JavaScript 核心模塊,從路徑分析、文件定位到編譯執(zhí)行,經(jīng)歷了一系列復(fù)雜的過(guò)程。簡(jiǎn)單的了解 Node 模塊的原理,有利于我們重新認(rèn)識(shí)基于 Node 搭建的...

    jsyzchen 評(píng)論0 收藏0
  • 前端性能優(yōu)化(三)——傳統(tǒng) JavaScript 優(yōu)化的誤區(qū)

    摘要:二模塊化誤區(qū)加快加載和執(zhí)行的速度,一直是前端優(yōu)化的一個(gè)熱點(diǎn)。結(jié)果文件減少,也達(dá)到了預(yù)期的效果。避免不必要的延遲。最后再根據(jù)文件的功能類型,來(lái)決定是放在頁(yè)面的頭部還是尾部。 注:本文是純技術(shù)探討文,無(wú)圖無(wú)笑點(diǎn),希望您喜歡 一.前言 軟件行業(yè)極其缺乏前端人才這是圈內(nèi)的共識(shí)了,某種程度上講,同等水平前端的工資都要比后端高上不少,而圈內(nèi)的另一項(xiàng)共識(shí)則是——網(wǎng)頁(yè)是公司的臉面! 幾年前,谷歌的一項(xiàng)...

    UsherChen 評(píng)論0 收藏0
  • JavaScript模塊化編程探索

    摘要:模塊化編程,已經(jīng)成為一個(gè)迫切的需求。隨著網(wǎng)站功能逐漸豐富,網(wǎng)頁(yè)中的也變得越來(lái)越復(fù)雜和臃腫,原有通過(guò)標(biāo)簽來(lái)導(dǎo)入一個(gè)個(gè)的文件這種方式已經(jīng)不能滿足現(xiàn)在互聯(lián)網(wǎng)開(kāi)發(fā)模式,我們需要團(tuán)隊(duì)協(xié)作模塊復(fù)用單元測(cè)試等等一系列復(fù)雜的需求。 隨著網(wǎng)站逐漸變成互聯(lián)網(wǎng)應(yīng)用程序,嵌入網(wǎng)頁(yè)的Javascript代碼越來(lái)越龐大,越來(lái)越復(fù)雜。網(wǎng)頁(yè)越來(lái)越像桌面程序,需要一個(gè)團(tuán)隊(duì)分工協(xié)作、進(jìn)度管理、單元測(cè)試等等......開(kāi)發(fā)...

    jayzou 評(píng)論0 收藏0
  • Node.js隨手筆記(一):node簡(jiǎn)介與模塊系統(tǒng)

    摘要:模塊系統(tǒng)為了讓的文件可以相互調(diào)用,提供了一個(gè)簡(jiǎn)單的模塊系統(tǒng)。但是,沒(méi)有模塊系統(tǒng)。包管理簡(jiǎn)稱,是隨同一起安裝的包管理工具。輸入命令,根據(jù)提示配置包的相關(guān)信息,生成相應(yīng)的。以上所描述的模塊載入機(jī)制均定義在模塊之中。 Node.js簡(jiǎn)介 首先從名字說(shuō)起,網(wǎng)上查閱資料的時(shí)候會(huì)發(fā)現(xiàn)關(guān)于node的寫法五花八門,到底哪一種寫法最標(biāo)準(zhǔn)呢?遵循官方網(wǎng)站的說(shuō)法,一直將項(xiàng)目稱之為Node或者Node.js。...

    TNFE 評(píng)論0 收藏0
  • 淺談 JavaScript 模塊化編程

    摘要:與在模塊化編程的世界中,有兩個(gè)規(guī)范不得不提,它們分別是和。所有依賴于某個(gè)模塊的代碼全部移到模塊加載語(yǔ)句的回調(diào)函數(shù)中去。的語(yǔ)句接受兩個(gè)參數(shù)在回調(diào)函數(shù)中,可以通過(guò)變量引用模塊。回調(diào)函數(shù)的返回值就是當(dāng)前對(duì)象的導(dǎo)出值。 JavaScript本身不是一種模塊化語(yǔ)言,設(shè)計(jì)者在創(chuàng)造JavaScript之初應(yīng)該也沒(méi)有想到這么一個(gè)腳本語(yǔ)言的作用領(lǐng)域會(huì)越來(lái)越大。以前一個(gè)頁(yè)面的JS代碼再多也不會(huì)多到哪兒去,...

    wdzgege 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<