摘要:語言官方未實(shí)現(xiàn)命名空間,我們定義一個函數(shù)以實(shí)現(xiàn)命名空間。函數(shù)的使用如我們可以這樣實(shí)現(xiàn)對象保存著所有已加載的模塊每一個模塊實(shí)例都有屬性作為時查找的標(biāo)識符,屬性作為對外暴露的對象,屬性表示是否加載完。將函數(shù)傳入,來支持模塊內(nèi)引用其他模塊。
JavaScript語言官方未實(shí)現(xiàn)命名空間,我們定義一個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 對象保存著所有已加載的模塊 var rootModule = {}; // 每一個模塊實(shí)例都有id屬性作為require時查找的標(biāo)識符, // exports屬性作為對外暴露的對象,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) { // 手動賦值模塊id,兼容一個script里有多個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)加載過直接返回module.exports, // 如果沒有加載過則通過jsonp加載,并且拋出一個異常來打斷原函數(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,來支持模塊內(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);
這個模塊加載的實(shí)現(xiàn)有很多不足,如果模塊內(nèi)有很多require時會被執(zhí)行很多次,所以最好子模塊內(nèi)都是函數(shù)不要有自己的狀態(tài)。seajs的依賴解決方法是,調(diào)用函數(shù)的toString方法來獲得函數(shù)字面量,然后在parse出模塊依賴,先加載依賴,每一個依賴加載完成后都emit一個事件,當(dāng)所有依賴都加載完畢后,才執(zhí)行factory函數(shù),factory函數(shù)只執(zhí)行一次,但是模塊加載的順序和require的順序基本沒有關(guān)系(并發(fā)請求,誰都有可能先到)。
======= 一本正經(jīng)的分割線 ======
順便吐槽一下seajs,由于某種原因,我再8102年見到了seajs而我在3000年前沒用過。文檔始終沒有交代require("caonima");是如何打斷函數(shù)執(zhí)行的。看了源碼發(fā)現(xiàn)是用了Function.prototype.toString方法,然后分析依賴并發(fā)加載(require函數(shù)是沒有順序之分的)。看源碼前,我自己為了模擬該行為,通過拋出異常再反復(fù)的重新執(zhí)行也實(shí)現(xiàn)了一個文件加載,而且我這個更賤的貨還是真的同步引入依賴,更加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)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/95627.html
摘要:例如指定一些依賴到模塊中實(shí)現(xiàn)規(guī)范的模塊化,感興趣的可以查看的文檔。 CommonJS 定義了 module、exports 和 require 模塊規(guī)范,Node.js 為了實(shí)現(xiàn)這個簡單的標(biāo)準(zhǔn),從底層 C/C++ 內(nèi)建模塊到 JavaScript 核心模塊,從路徑分析、文件定位到編譯執(zhí)行,經(jīng)歷了一系列復(fù)雜的過程。簡單的了解 Node 模塊的原理,有利于我們重新認(rèn)識基于 Node 搭建的...
摘要:二模塊化誤區(qū)加快加載和執(zhí)行的速度,一直是前端優(yōu)化的一個熱點(diǎn)。結(jié)果文件減少,也達(dá)到了預(yù)期的效果。避免不必要的延遲。最后再根據(jù)文件的功能類型,來決定是放在頁面的頭部還是尾部。 注:本文是純技術(shù)探討文,無圖無笑點(diǎn),希望您喜歡 一.前言 軟件行業(yè)極其缺乏前端人才這是圈內(nèi)的共識了,某種程度上講,同等水平前端的工資都要比后端高上不少,而圈內(nèi)的另一項(xiàng)共識則是——網(wǎng)頁是公司的臉面! 幾年前,谷歌的一項(xiàng)...
摘要:模塊化編程,已經(jīng)成為一個迫切的需求。隨著網(wǎng)站功能逐漸豐富,網(wǎng)頁中的也變得越來越復(fù)雜和臃腫,原有通過標(biāo)簽來導(dǎo)入一個個的文件這種方式已經(jīng)不能滿足現(xiàn)在互聯(lián)網(wǎng)開發(fā)模式,我們需要團(tuán)隊(duì)協(xié)作模塊復(fù)用單元測試等等一系列復(fù)雜的需求。 隨著網(wǎng)站逐漸變成互聯(lián)網(wǎng)應(yīng)用程序,嵌入網(wǎng)頁的Javascript代碼越來越龐大,越來越復(fù)雜。網(wǎng)頁越來越像桌面程序,需要一個團(tuán)隊(duì)分工協(xié)作、進(jìn)度管理、單元測試等等......開發(fā)...
摘要:模塊系統(tǒng)為了讓的文件可以相互調(diào)用,提供了一個簡單的模塊系統(tǒng)。但是,沒有模塊系統(tǒng)。包管理簡稱,是隨同一起安裝的包管理工具。輸入命令,根據(jù)提示配置包的相關(guān)信息,生成相應(yīng)的。以上所描述的模塊載入機(jī)制均定義在模塊之中。 Node.js簡介 首先從名字說起,網(wǎng)上查閱資料的時候會發(fā)現(xiàn)關(guān)于node的寫法五花八門,到底哪一種寫法最標(biāo)準(zhǔn)呢?遵循官方網(wǎng)站的說法,一直將項(xiàng)目稱之為Node或者Node.js。...
摘要:與在模塊化編程的世界中,有兩個規(guī)范不得不提,它們分別是和。所有依賴于某個模塊的代碼全部移到模塊加載語句的回調(diào)函數(shù)中去。的語句接受兩個參數(shù)在回調(diào)函數(shù)中,可以通過變量引用模塊。回調(diào)函數(shù)的返回值就是當(dāng)前對象的導(dǎo)出值。 JavaScript本身不是一種模塊化語言,設(shè)計(jì)者在創(chuàng)造JavaScript之初應(yīng)該也沒有想到這么一個腳本語言的作用領(lǐng)域會越來越大。以前一個頁面的JS代碼再多也不會多到哪兒去,...
閱讀 1408·2021-09-23 11:21
閱讀 3105·2019-08-30 14:14
閱讀 3187·2019-08-30 13:56
閱讀 4136·2019-08-30 11:20
閱讀 1949·2019-08-29 17:23
閱讀 2765·2019-08-29 16:14
閱讀 1693·2019-08-28 18:18
閱讀 1490·2019-08-26 12:14