require簡單實現

requ(path){
        // 找到路徑,引進代碼字符串
        // let code = load(path)
        let code = 'function add(a, b) {return a+b}; module.exports = add'
        code = `(function(module){${code}})(context)`

        // 此處context就是內部的module
        let context = {}
        const run = new Function('context',code)
        run(context)

        return context.exports
    }

在瀏覽器環境,所有的 Js 模塊都需要遠程讀取,尷尬的是,受限于瀏覽器提供的能力,并不能通過 ajax 以文件流的形式將遠程的 js 文件直接讀取為字符串代碼。前提條件無法達成,上述運行策略便行不通,只能另辟蹊徑

這就是為什么有了 CommonJs 規范了,為什么還會出現 AMD/CMD 規范的原因

那么瀏覽器上是怎么做的呢?在瀏覽器中通過 Js 控制動態的載入一個遠程的 Js 模塊文件,需要動態的插入一個 <script> 節點:

// 摘抄自 require.js 的一段代碼
var node = config.xhtml ?
                document.createElementNS('http://www.w3.org/1999/xhtml', 'html:script') :
                document.createElement('script');
node.type = config.scriptType || 'text/javascript';
node.charset = 'utf-8';
node.async = true;
node.setAttribute('data-requirecontext', context.contextName);
node.setAttribute('data-requiremodule', moduleName);
node.addEventListener('load', context.onScriptLoad, false);
node.addEventListener('error', context.onScriptError, false);

要知道,設置了 <script> 標簽的 src 之后,代碼一旦下載完成,就會立即執行,根本由不得你再封裝成閉包,所以文件模塊需要在定義之初就要做文章,這就是我們說熟知的 AMD/CMD 規范中的 define,開篇的 add.js 需要重新改寫一下

// add.js 文件
define ('add',function () {
    function add (a, b) {
      return a + b;
    }
    return add;
})

而對于 define 的實現,最重要的就是將 callback 的執行結果注冊到 context 的一個模塊數組中:

context.modules = {}
    function define(name, callback) {
        context.modules[name] = callback && callback()
    }

AMD 和 CMD 的差異主要是,前者需要在定義之初聲明所有的依賴,后者可以在任意時機動態引入模塊。CMD 更接近于 CommonJS

兩種規范都需要從遠程網絡中載入模塊,不同之處在于,前者是預加載,后者是延遲加載

參考自Js 中的模塊化是如何達成的

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容