摘要:目前通行的的模板規(guī)范共有兩種和的模塊系統(tǒng),是參照規(guī)范實(shí)現(xiàn)的即為服務(wù)器端模塊的規(guī)范。規(guī)范則是非同步加載模塊,允許指定回調(diào)函數(shù)。
目前通行的Javascript的模板規(guī)范共有兩種:CommonJS 和 AMD commonjs
nodejs的模塊系統(tǒng),是參照commonjs規(guī)范實(shí)現(xiàn)的
commonjs即為服務(wù)器端模塊的規(guī)范。 commonjs的規(guī)范: 根據(jù)commonjs規(guī)范,一個多帶帶的文件就是一個模塊。加載模塊使用require方法,該方法讀取一個文件并執(zhí)行,最后返回文件內(nèi)部的exports對象
commonjs模塊的加載原理commonjs模塊無論加載多少次,都只會在第一次加載時運(yùn)行一次,以后再加載,就返回第一次運(yùn)行的結(jié)果,除非手動清除系統(tǒng)緩存。
AMDcommonjs規(guī)范加載模塊是同步的,也就是說,只有加載完成,才能執(zhí)行后面的操作。AMD規(guī)范則是非同步加載模塊,允許指定回調(diào)函數(shù)。由于Node.js主要用于服務(wù)器編程,模塊文件一般都已經(jīng)存在于本地硬盤,所以加載起來比較快,不用考慮非同步加載的方式,所以commonjs規(guī)范比較適用。但是,如果是瀏覽器環(huán)境,要從服務(wù)器端加載模塊,這時就必須采用非同步模式,因此瀏覽器端一般采用AMD規(guī)范。
可以理解為AMD即為能在客戶端環(huán)境,并且能兼容服務(wù)器端模塊的一種模塊規(guī)范
AMD的模塊定義:
AMD規(guī)范使用define方法定義模塊
Define第一個參數(shù)表達(dá)依賴的模塊數(shù)組,第二個為加載完依賴的模塊數(shù)組后,模塊執(zhí)行的函數(shù)
AMD的模塊加載定義:跟commonjs一樣,AMD也采用require()語句來加載模塊,但是與commonjs不同的是,它要求有兩個參數(shù):
第一個參數(shù)[module],是一個數(shù)組,里面的成員就是要加載的模塊;第二個參數(shù)callback,則是加載成功之后的回調(diào)函數(shù)
對于依賴的模塊,AMD是提前執(zhí)行,CMD是延遲執(zhí)行。不過 RequireJS 從 2.0 開始,也改成可以延遲執(zhí)行(根據(jù)寫法不同,處理方式不同)。CMD推崇 as lazy as possible.
CMD推崇依賴就近,AMD推崇依賴前置
AMD的API默認(rèn)是一個當(dāng)多個用,CMD的API 嚴(yán)格區(qū)分,推崇職責(zé)單一。比如AMD里,require分全局require和局部require,都叫require。CMD里,沒有全局 require,而是根據(jù)模塊系統(tǒng)的完備性,提供seajs.use來實(shí)現(xiàn)模塊系統(tǒng)的加載啟動。CMD里,每個API都簡單純粹。
ES6 ModulesES6模塊的設(shè)計(jì)思想,是盡量的靜態(tài)化,使得編譯時就能確定模塊的依賴關(guān)系,以及輸入和輸出的變量。commonjs和AMD模塊,都只能在運(yùn)行時確定這些東西。比如,commonjs模塊就是對象,輸入時必須查找對象屬性。
// CommonJS模塊 let { stat, exists, readFile } = require("fs"); // 等同于 let _fs = require("fs"); let stat = _fs.stat, exists = _fs.exists, readfile = _fs.readfile;
上面代碼的實(shí)質(zhì)是整體加載fs模塊(即加載fs的所有方法),生成一個對象(_fs),然后再從這個對象上面讀取3個方法。這種加載稱為“運(yùn)行時加載”,因?yàn)橹挥羞\(yùn)行時才能得到這個對象,導(dǎo)致完全沒辦法在編譯時做“靜態(tài)優(yōu)化”。
ES6模塊不是對象,而是通過export命令顯式指定輸出的代碼,輸入時也采用靜態(tài)命令的形式。
// ES6模塊 import { stat, exists, readFile } from "fs";
上面代碼的實(shí)質(zhì)是從fs模塊加載3個方法,其他方法不加載。這種加載稱為“編譯時加載”,即ES6可以在編譯時就完成模塊加載,效率要比CommonJS模塊的加載方式高。當(dāng)然,這也導(dǎo)致了沒法引用ES6模塊本身,因?yàn)樗皇菍ο蟆?/p>
由于ES6模塊是編譯時加載,使得靜態(tài)分析成為可能。有了它,就能進(jìn)一步拓寬JavaScript的語法,比如引入宏(macro)和類型檢驗(yàn)(type system)這些只能靠靜態(tài)分析實(shí)現(xiàn)的功能。
除了靜態(tài)加載帶來的各種好處,ES6模塊還有以下好處。
不再需要UMD模塊格式了,將來服務(wù)器和瀏覽器都會支持ES6模塊格式。目前,通過各種工具庫,其實(shí)已經(jīng)做到了這一點(diǎn)。
將來瀏覽器的新API就能用模塊格式提供,不再必要做成全局變量或者navigator對象的屬性。
不再需要對象作為命名空間(比如Math對象),未來這些功能可以通過模塊提供。
瀏覽器使用ES6模塊的語法如下。
上面代碼在網(wǎng)頁中插入一個模塊foo.js,由于type屬性設(shè)為module,所以瀏覽器知道這是一個ES6模塊。
Node的默認(rèn)模塊格式是CommonJS,目前還沒決定怎么支持ES6模塊。所以,只能通過Babel這樣的轉(zhuǎn)碼器,在Node里面使用ES6模塊。
用法export
優(yōu)先考慮這種寫法而不是一個一個的export
// profile.js var firstName = "Michael"; var lastName = "Jackson"; var year = 1958; export {firstName, lastName, year};
提供對外接口必須在接口名與模塊內(nèi)部變量之間保持一一對應(yīng)關(guān)系
// 報(bào)錯 function f() {} export f; // 正確 export function f() {}; // 正確 function f() {} export {f};
最后,export命令可以出現(xiàn)在模塊的任何位置,只要處于模塊頂層就可以。如果處于塊級作用域內(nèi),就會報(bào)錯,下一節(jié)的import命令也是如此。這是因?yàn)樘幱跅l件代碼塊之中,就沒法做靜態(tài)優(yōu)化了,違背了ES6模塊的設(shè)計(jì)初衷。
import
使用export命令定義了模塊的對外接口以后,其他JS文件就可以通過import命令加載這個模塊(文件)。
// main.js import {firstName, lastName, year} from "./profile"; function setName(element) { element.textContent = firstName + " " + lastName; }
上面代碼的import命令,就用于加載profile.js文件,并從中輸入變量。import命令接受一個對象(用大括號表示),里面指定要從其他模塊導(dǎo)入的變量名。大括號里面的變量名,必須與被導(dǎo)入模塊(profile.js)對外接口的名稱相同。
如果想為輸入的變量重新取一個名字,import命令要使用as關(guān)鍵字,將輸入的變量重命名。
import { lastName as surname } from "./profile";
注意,import命令具有提升效果,會提升到整個模塊的頭部,首先執(zhí)行。
ES6模塊加載的實(shí)質(zhì)ES6模塊加載的機(jī)制,與CommonJS模塊完全不同。CommonJS模塊輸出的是一個值的拷貝,而ES6模塊輸出的是值的引用。
ES6的輸入有點(diǎn)像Unix系統(tǒng)的“符號連接”,原始值變了,import輸入的值也會跟著變。因此,ES6模塊是動態(tài)引用,并且不會緩存值,模塊里面的變量綁定其所在的模塊。
IMWEB團(tuán)隊(duì)博客
知乎問答
阮一峰老師的ES6教程
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/86432.html
摘要:引言最近在學(xué)習(xí),發(fā)現(xiàn)好多知識點(diǎn),之前一點(diǎn)都沒有接觸過,如等等。使用本地安裝,會存于文件夾內(nèi)與屬性內(nèi),更方便項(xiàng)目文件遷移以及協(xié)同開發(fā)等情況。 引言 最近在學(xué)習(xí)webpack,發(fā)現(xiàn)好多知識點(diǎn),之前一點(diǎn)都沒有接觸過,如babel、core-js、browserslist等等。以前習(xí)慣了使用cli構(gòu)建項(xiàng)目,很多東西不用考慮,拿來就用,這樣的碼農(nóng)是不會有能力提升的,必須了解更多的知識點(diǎn),才能成為...
摘要:在開發(fā)大型的項(xiàng)目中,可能會使用到管理的模塊化工具。說道,學(xué)習(xí)過的同學(xué)會比較熟悉,是服務(wù)器模塊的規(guī)范,采用了這個規(guī)范??赡苁俏磥砟K化解決方案的首選。 本文章記錄本人在學(xué)習(xí) JavaScript 中理解到的一些東西,加深記憶和并且整理記錄下來,方便之后的復(fù)習(xí)。 在開發(fā)大型的web項(xiàng)目中,可能會使用到管理js的模塊化工具。但是在前端輪子漫天飛的時代。那一款js模塊化工具真正適合我...
摘要:國內(nèi)各大公司都已經(jīng)投入使用,在一些常見的網(wǎng)站,如淘寶騰訊小米等移動站點(diǎn),隨處可見其蹤影。變革之騰訊手機(jī)淘寶的設(shè)計(jì)與實(shí)現(xiàn)前端亂燉適配總結(jié)樣式重置上文已提及,這里推薦閱讀同學(xué)寫的專題文章。 前言 CSS代碼難維護(hù)眾所皆知。 為一個元素設(shè)置樣式的方式可以通過定義的class、定義的id、元素的標(biāo)簽名、元素的屬性等選擇器以及這些選擇器的組合來實(shí)現(xiàn); 作用于某個元素上的樣式又可能來自單個樣式規(guī)...
摘要:國內(nèi)各大公司都已經(jīng)投入使用,在一些常見的網(wǎng)站,如淘寶騰訊小米等移動站點(diǎn),隨處可見其蹤影。變革之騰訊手機(jī)淘寶的設(shè)計(jì)與實(shí)現(xiàn)前端亂燉適配總結(jié)樣式重置上文已提及,這里推薦閱讀同學(xué)寫的專題文章。 前言 CSS代碼難維護(hù)眾所皆知。 為一個元素設(shè)置樣式的方式可以通過定義的class、定義的id、元素的標(biāo)簽名、元素的屬性等選擇器以及這些選擇器的組合來實(shí)現(xiàn); 作用于某個元素上的樣式又可能來自單個樣式規(guī)...
摘要:前端期望中的設(shè)計(jì)能給予的除了之外,還有設(shè)計(jì)上游崗位傳遞下來的東西。份文件一份好的文件是分層清晰,設(shè)計(jì)規(guī)范的文件。有些頁面設(shè)計(jì)師沒有考慮到。地址如下原文鏈接我們前端是怎么跟設(shè)計(jì)師溝通的豪情博客園 1.交付 一般設(shè)計(jì)師給前端的只有psd,沒有其它多余的東西,連基本的文檔都懶得給。前端期望中的設(shè)計(jì)能給予的除了psd之外, 還有設(shè)計(jì)上游崗位傳遞下來的東西。 比如: 產(chǎn)品原型, 需求文檔, 交...
閱讀 3267·2021-11-24 10:30
閱讀 1381·2021-09-30 09:56
閱讀 2482·2021-09-07 10:20
閱讀 2673·2021-08-27 13:10
閱讀 784·2019-08-30 11:11
閱讀 2125·2019-08-29 12:13
閱讀 818·2019-08-26 12:24
閱讀 2989·2019-08-26 12:20