摘要:之前的面試中,一直感覺模塊化沒有什么可以問的,不過昨天面試突然想到一個題目對于一個的模式下文件如下很多代碼很多代碼很多代碼文件分別是什么時候加載的,如何加載的題目不難答案是和是在加載完后就加載。
模塊化現在應該已經成為了稍微復雜一點前端開發的標配了。在es6中,都已經支持了的模塊化。
之前的面試中,一直感覺模塊化AMD,CMD沒有什么可以問的,不過昨天面試突然想到一個題目:
對于一個AMD的模式下
文件d.js如下
define(function (require) { // ... 很多代碼 require("a"); // ... 很多代碼 require(["b"], function (b) {}); // ... 很多代碼 require("c"); });
a.js,b.js,c.js 文件分別是什么時候加載的,如何加載的?
題目不難
答案是a.js 和 c.js 是在加載完d.js后就加載。
b.js是在執行到這一行時異步加載的。
具體分析:
我沒有看過require.js的源碼,我們使用的是esl.js(也是一個AMD的模塊加載器),但是他們的實現原理應該差不多。
我從esl.js的角度解讀一下:
同步加載,異步加載首先大家需要知道AMD里面一個同步加載和異步加載的概念。
從概念上面理解,同步就是當我執行到require("a");時,我需要同步的執行a.js里面的內容,也就是需要在執行到這句話時a.js必須已經加載好了,這樣才能到達同步。
而對于 require(["b"], function (b) {});,我執行到這一步時,是異步的發出請求,然后異步等待b.js的返回+執行。
同步加載的實現原理我們從概念上面理解的同步加載的原理,現在看看esl.js的實踐。
這里面需要處理兩個核心步驟
執行到require("a");時,a.js必須已經加載好了;
a.js文件里面的所有require("*"),也都必須加載好了,保證在執行a.js時,所有a.js依賴的同步文件都能同步執行;
對于第一步的實現,大概原理是這樣的,在加載好了d.js后,會正則匹配一次文件里面的同步依賴require("*");,例如匹配出了 a.js和c.js,然后繼續加載a.js和c.js。
對于第二部,其實就是一個遞歸處理,直到沒有下一步的依賴為止。
同步加載另外一種處理方法上面有一部正則邏輯,可見如果使用這種方式,在執行代碼前,js需要全部正則一次所有模塊化代碼的。這樣性能是不是有一個無謂的耗損。
那么我們一般怎么處理了?
大家一般都了解過打包編譯,例如在使用Requirejs時,線上環境的代碼會經過r.js處理一次。
那么d.js文件應該會處理如下
define( "path/b", ["require", "a", "b"], function (require) { // ... 很多代碼 require("a"); // ... 很多代碼 require(["b"], function (b) {}); // ... 很多代碼 require("c"); });
define方法會增加第一個和第二個參數
第一個參數是按照路徑生成一個具名id
第二個參數是此文件所依賴的同步文件
這時當模塊在解析這個b,js文件時,發現如果存在第二個參數,就會直接解析所需依賴部分,而省去了正則這一步。
我們正則這一步轉換到了打包編譯中去分析,這樣就省掉了瀏覽器加載時去正則所有AMD文件這一步。
那么為什么我們不在開發環境中直接使用["require", "a", "b"]方式,我理解目的是為了提高開發便捷性,我們不需要再增加一個require("*")都在中括號內配置一次,同樣刪除時也不用去刪掉配置。
因為這一步完全可以在編譯時處理。
打包編譯的延生不知道大家有沒有看過編譯后的代碼和開發環境代碼的區別,對于這個d.js文件,編譯后應該是:
define( "path/a", ["require"], function (require) { // ... 很多代碼 }); define( "path/c", ["require"], function (require) { // ... 很多代碼 }); define( "path/b", ["require", "a", "b"], function (require) { // ... 很多代碼 require("a"); // ... 很多代碼 require(["b"], function (b) {}); // ... 很多代碼 require("c"); });
上面可見,a.js和c.js這兩個文件被合并到了d.js中,所有文件都加上了具名id。而且這個id的生成規則是更具路徑生成的。
而我們異步加載的b.js文件就沒有被打包進來。這是因為我們期望b.js是懶加載的,當使用時在加載,這樣也能達到按需加載的目的。
公眾號 博客地址http://tangguangyao.github.io/
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/78486.html
摘要:項目組長給我看了一道面試別人的面試題。打鐵趁熱,再來一道題來加深下理解。作者以樂之名本文原創,有不當的地方歡迎指出。 showImg(https://segmentfault.com/img/bVbur0z?w=600&h=400); 剛入職新公司,屬于公司萌新一枚,一天下午對著屏幕看代碼架構時。BI項目組長給我看了一道面試別人的JS面試題。 雖然答對了,但把理由說錯了,照樣不及格。 ...
摘要:重溫一個面試題內容數組內容為數組內容為個英文字母,使用兩個線程分別輸入兩個數組,打印內容為這樣的規律提取一下核心內容,去除次要內容兩個線程需要交替執行,打印數字的線程需要先執行,數組打印完畢后線程需要結束。 一道多線程面試題引起的自我救贖 近日去一個知名互聯網企業參加面試,之前準備多多信心滿滿,但是面試一開始就是一道不起眼的編程題 數組A內容為 1,2,3,4...52 ,數組B內容...
摘要:一基礎接口的意義百度規范擴展回調抽象類的意義我的前端面試經歷百度前端掘金博主就讀于電子科技大學,大三狗一枚面試是個漫長的過程,從海投到收獲電話面試,一面二面三面,一個步驟出錯那么后面就宣告終結。 一道常被人輕視的前端 JS 面試題 - 前端 - 掘金 目錄前言第一問第二問變量聲明提升函數表達式第三問第四問第五問第六問構造函數的返回值第七問最后前言 年前剛剛離職了,分享下我曾經出過的一道...
閱讀 2148·2023-04-25 18:49
閱讀 1853·2019-08-30 14:02
閱讀 2656·2019-08-29 17:24
閱讀 3333·2019-08-28 18:10
閱讀 2937·2019-08-28 18:03
閱讀 499·2019-08-26 12:01
閱讀 3319·2019-08-26 11:31
閱讀 1441·2019-08-26 10:29