摘要:參考資料前端模塊化詳解完整版入門近一萬字的語法知識點補充徹底搞清楚中的和和詳解
前言
前端的模塊化之路經歷了漫長的過程,想詳細了解的小伙伴可以看浪里行舟大神寫的前端模塊化詳解(完整版),這里根據幾位大佬們寫的文章,將模塊化規范部分做了匯總和整理,希望讀完的小伙伴能有些收獲,也希望覺得有用的小伙伴可以點個贊,筆芯。
什么是模塊將一個復雜的程序依據一定的規則(規范)封裝成幾個塊(文件), 并進行組合在一起
塊的內部數據與實現是私有的,只是向外部暴露一些接口(方法)與外部其它模塊通信
CommonJSNode 應用由模塊組成,采用 CommonJS 模塊規范。每個文件就是一個模塊,有自己的作用域。在一個文件里面定義的變量、函數、類,都是私有的,對其他文件不可見。在服務器端,模塊的加載是運行時同步加載的;在瀏覽器端,模塊需要提前編譯打包處理。
CommonJS規范加載模塊是同步的,也就是說,只有加載完成,才能執行后面的操作。
基本語法:
暴露模塊:module.exports = value 或 exports.xxx = value
引入模塊:require(xxx),如果是第三方模塊,xxx為模塊名;如果是自定義模塊,xxx為模塊文件路徑
但是,CommonJs有一個重大的局限使得它不適用于瀏覽器環境,那就是require操作是同步的。這對服務器端不是一個問題,因為所有的模塊都存放在本地硬盤,可以同步加載完成,等待時間就是硬盤的讀取時間。但是,對于瀏覽器,這卻是一個大問題,因為模塊都放在服務器端,等待時間取決于網速的快慢,可能要等很長時間,瀏覽器處于”假死”狀態。
因此,瀏覽器端的模塊,不能采用”同步加載”(synchronous),只能采用”異步加載”(asynchronous),這就是AMD規范誕生的背景。
AMD特點:非同步加載模塊,允許指定回調函數,瀏覽器端一般采用AMD規范
代表作:require.js
用法:
//定義沒有依賴的模塊 define(function(){ return 模塊 }) //定義有依賴的模塊 define(["module1", "module2"], function(m1, m2){ return 模塊 }) //引入使用模塊 require(["module1", "module2"], function(m1, m2){ //使用m1/m2 })CMD
特點:專門用于瀏覽器端,模塊的加載是異步的,模塊使用時才會加載執行
代表作:Sea.js
用法:
//定義沒有依賴的模塊 define(function(require, exports, module){ exports.xxx = value module.exports = value }) //定義有依賴的模塊 define(function(require, exports, module){ //引入依賴模塊(同步) var module2 = require("./module2") //引入依賴模塊(異步) require.async("./module3", function (m3) { }) //暴露模塊 exports.xxx = value }) //引入使用模塊 define(function (require) { var m1 = require("./module1") var m4 = require("./module4") m1.show() m4.show() })CMD與AMD區別
AMD和CMD最大的區別是對依賴模塊的執行時機處理不同,而不是加載的時機或者方式不同,二者皆為異步加載模塊。
AMD依賴前置,js可以方便知道依賴模塊是誰,立即加載;
而CMD就近依賴,需要使用把模塊變為字符串解析一遍才知道依賴了那些模塊,這也是很多人詬病CMD的一點,犧牲性能來帶來開發的便利性,實際上解析模塊用的時間短到可以忽略。
一句話總結:
兩者都是異步加載,只是執行時機不一樣。AMD是依賴前置,提前執行,CMD是依賴就近,延遲執行。
UMD是AMD和CommonJS的糅合:
AMD模塊以瀏覽器第一的原則發展,異步加載模塊。
CommonJS模塊以服務器第一原則發展,選擇同步加載,它的模塊無需包裝(unwrapped modules)。
這迫使人們又想出另一個更通用的模式UMD (Universal Module Definition)。希望解決跨平臺的解決方案。
UMD先判斷是否支持Node.js的模塊(exports)是否存在,存在則使用Node.js模塊模式。
在判斷是否支持AMD(define是否存在),存在則使用AMD方式加載模塊。
(function (window, factory) { if (typeof exports === "object") { module.exports = factory(); } else if (typeof define === "function" && define.amd) { define(factory); } else { window.eventUtil = factory(); } })(this, function () { //module ... });ES6模塊化
ES6 模塊的設計思想是盡量的靜態化,使得編譯時就能確定模塊的依賴關系,以及輸入和輸出的變量。CommonJS 和 AMD 模塊,都只能在運行時確定這些東西。比如,CommonJS 模塊就是對象,輸入時必須查找對象屬性。
ES6 Module默認目前還沒有被瀏覽器支持,需要使用babel,在日常寫demo的時候經常會顯示這個錯誤:
ES6模塊使用import關鍵字導入模塊,export關鍵字導出模塊:
/** 導出模塊的方式 **/ var a = 0; export { a }; //第一種 export const b = 1; //第二種 let c = 2; export default { c }//第三種 let d = 2; export default { d as e }//第四種,別名 /** 導入模塊的方式 **/ import { a } from "./a.js" //針對export導出方式,.js后綴可省略 import main from "./c" //針對export default導出方式,使用時用 main.c import "lodash" //僅僅執行lodash模塊,但是不輸入任何值命名式導出與默認導出
export {<變量>}這種方式一般稱為 命名式導出 或者 具名導出,導出的是一個變量的引用。
export default這種方式稱為 默認導出 或者 匿名導出,導出的是一個值。
舉例:
// a.js let x = 10 let y = 20 setTimeout(()=>{ x = 100 y = 200 },100) export { x } export default y // b.js import { x } from "./a.js" import y from "./a.js" setTimeout(()=>{ console.log(x,y) // 100,20 },100)ES6 模塊與 CommonJS 模塊的差異
① CommonJS 模塊輸出的是一個值的拷貝,ES6 模塊輸出的是值的引用。
CommonJS 模塊輸出的是值的拷貝,也就是說,一旦輸出一個值,模塊內部的變化就影響不到這個值。而且,CommonJS 模塊無論加載多少次,都只會在第一次加載時運行一次,以后再加載,返回的都是第一次運行結果的緩存,除非手動清除系統緩存。
?ES6 模塊的運行機制與 CommonJS 不一樣,JS 引擎對腳本靜態分析的時候,遇到模塊加載命令import,就會生成一個只讀引用,等到腳本真正執行時,再根據這個只讀引用,到被加載的那個模塊里面去取值。換句話說,ES6 的import有點像 Unix 系統的“符號連接”,原始值變了,import加載的值也會跟著變。因此,ES6 模塊是動態引用,并且不會緩存值,模塊里面的變量綁定其所在的模塊。
② CommonJS 模塊是運行時加載,ES6 模塊是編譯時輸出接口。
CommonJS 加載的是一個對象(即module.exports屬性),該對象只有在腳本運行完才會生成。即在輸入時是先加載整個模塊,生成一個對象,然后再從這個對象上面讀取方法,這種加載稱為“運行時加載”。
例如:
// CommonJS模塊 let { stat, exists, readFile } = require("fs"); // 等同于 let _fs = require("fs"); let stat = _fs.stat; let exists = _fs.exists; let readfile = _fs.readfile;
上面代碼的實質是整體加載fs模塊(即加載fs的所有方法),生成一個對象(_fs),然后再從這個對象上面讀取 3 個方法。因為只有運行時才能得到這個對象,導致完全沒辦法在編譯時做“靜態優化”。
ES6 模塊不是對象,它的對外接口只是一種靜態定義,在代碼靜態解析階段就會生成。通過export命令顯式指定輸出的代碼,import時采用靜態命令的形式。即在import時可以指定加載某個輸出值,而不是加載整個模塊,這種加載稱為“編譯時加載”或者“靜態加載”。
// ES6模塊 import { stat, exists, readFile } from "fs";
上面代碼的實質是從fs模塊加載 3 個方法,其他方法不加載。即 ES6 可以在編譯時就完成模塊加載,效率要比 CommonJS 模塊的加載方式高。當然,這也導致了沒法引用 ES6 模塊本身,因為它不是對象。
由于 ES6 模塊是編譯時加載,使得靜態分析成為可能。有了它,就能進一步拓寬 JavaScript 的語法,比如引入宏(macro)和類型檢驗(type system)這些只能靠靜態分析實現的功能。
除了靜態加載帶來的各種好處,ES6 模塊還有以下好處:
不再需要UMD模塊格式了,將來服務器和瀏覽器都會支持 ES6 模塊格式。目前,通過各種工具庫,其實已經做到了這一點。
將來瀏覽器的新API 就能用模塊格式提供,不再必須做成全局變量或者navigator對象的屬性。
不再需要對象作為命名空間(比如Math對象),未來這些功能可以通過模塊提供。
總結CommonJS規范主要用于服務端編程,加載模塊是同步的,這并不適合在瀏覽器環境,因為同步意味著阻塞加載,瀏覽器資源是異步加載的,因此有了AMD、CMD解決方案。
AMD規范在瀏覽器環境中異步加載模塊,而且可以并行加載多個模塊。不過,AMD規范開發成本高,代碼的閱讀和書寫比較困難,模塊定義方式的語義不順暢。
CMD規范與AMD規范很相似,都用于瀏覽器編程,依賴就近,延遲執行,可以很容易在Node.js中運行。不過,依賴SPM打包,模塊的加載邏輯偏重。
ES6 在語言標準的層面上,實現了模塊功能,而且實現得相當簡單,完全可以取代 CommonJS 和 AMD 規范,成為瀏覽器和服務器通用的模塊解決方案。
以上是本篇文章的內容,歡迎大家提出自己的想法,我們一起學習進步,與君共勉。
參考資料前端模塊化詳解(完整版)
ECMAScript 6 入門
近一萬字的ES6語法知識點補充
徹底搞清楚javascript中的require、import和export
CommonJS,AMD,CMD,ES6,require 和 import 詳解
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/103893.html
摘要:語料庫是由文本構成的數據集通過提供現成的文本數據來輔助文本處理。那么可以用來做什么呢我自己是一名從事是不錯的入門選項。大數據和人工智能是機器學習和的主要開發語言。 Python培訓有哪些內容?很多零基礎學員不知道Python軟件是干什么用的?Python軟件是Python工程師編寫代碼時所需...
摘要:的屬性在瀏覽器的控制臺中,可以直接輸入來查看。可以在瀏覽器的控制臺中看出哪些是類型的,下帶綠色對勾的即是,如圖只要是類型的在控制臺通過是獲取不到的,也不能進行修改。當會話過期或被放棄后,服務器將終止該會話。在中,用取代了。 本文由云+社區發表 在前端面試中,有一個必問的問題:請你談談cookie和localStorage有什么區別啊? localStorage是H5中的一種瀏覽器本地存...
摘要:以餃子為例,這時候需要準備好面粉,剁好的餡料,再調配好需要的配料,還得等面粉發酵完畢后和面。包好餃子放進蒸屜之中,蒸好后才能享用。與在自己家里面做不同,這里需要一個餃子的供應商,這就是基礎設施即服務。在與相關人士聊云計算的時候,有時會從他們的最終蹦出諸如IaaS、PaaS和SaaS等相關名詞,聽的人一頭霧水,而往往與你聊的人,也只能用一些專業名字來解釋,這樣一來,就更加疑惑了。那么IaaS、...
摘要:因此,年的埃里克施密特首次提出了云計算的概念,以及后來業界衍生出來霧計算霾計算邊緣計算等等一系列的計算方式,接下來,請跟隨小編一起去辨析一下它們到底指的是什么。未來的世界將是一個萬物互聯的時代,隨著物聯網行業技術標準的完善以及關鍵技術上的不斷突破,數據大爆炸時代將越走越近。就拿從2016年底開始風靡全國甚至是海外市場的共享單車來說吧,據小編近日從摩數城市發布會獲悉,截止當前,僅僅摩拜單車每天...
閱讀 1370·2021-11-22 09:34
閱讀 2581·2021-11-12 10:36
閱讀 1111·2021-11-11 16:55
閱讀 2324·2020-06-22 14:43
閱讀 1457·2019-08-30 15:55
閱讀 1975·2019-08-30 15:53
閱讀 1764·2019-08-30 10:50
閱讀 1217·2019-08-29 12:15