亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 網站 > WEB開發 > 正文

javascript模塊化之CommonJS、AMD、CMD、UMD、ES6

2024-04-27 15:06:38
字體:
來源:轉載
供稿:網友

這是一篇關于js模塊化編程的總結記錄

隨著網站逐漸變成”互聯網應用程序”,嵌入網頁的javascript代碼越來越龐大,越來越復雜。

網頁越來越像桌面程序,需要一個團隊分工協作、進度管理、單元測試等等……開發者不得不使用軟件工程的方法,管理網頁的業務邏輯。

Javascript模塊化編程,已經成為一個迫切的需求。理想情況下,開發者只需要實現核心的業務邏輯,其他都可以加載別人已經寫好的模塊。

Javascript社區做了很多努力,在現有的運行環境中,實現”模塊”的效果。

CommonJS

這里的CommonJS規范指的是CommonJS Modules/1.0規范。

CommonJS是一個更偏向于服務器端的規范。NodeJS采用了這個規范。CommonJS的一個模塊就是一個腳本文件。require命令第一次加載該腳本時就會執行整個腳本,然后在內存中生成一個對象。

{ id: '...', exports: { ... }, loaded: true, ...}

id是模塊名,exports是該模塊導出的接口,loaded表示模塊是否加載完畢。此外還有很多屬性,這里省略了。

以后需要用到這個模塊時,就會到exports屬性上取值。即使再次執行require命令,也不會再次執行該模塊,而是到緩存中取值。

// math.jsexports.add = function(a, b) { return a + b;}var math = require('math');math.add(2, 3); // 5

由于CommonJS是同步加載模塊,這對于服務器端不是一個問題,因為所有的模塊都放在本地硬盤。等待模塊時間就是硬盤讀取文件時間,很小。但是,對于瀏覽器而言,它需要從服務器加載模塊,涉及到網速,代理等原因,一旦等待時間過長,瀏覽器處于”假死”狀態。

所以在瀏覽器端,不適合于CommonJS規范。所以在瀏覽器端又出現了一個規范—-AMD。

AMD

CommonJS解決了模塊化的問題,但這種同步加載方式并不適合于瀏覽器端。

AMD是”Asynchronous Module Definition”的縮寫,即”異步模塊定義”。它采用異步方式加載模塊,模塊的加載不影響它后面語句的運行。 這里異步指的是不堵塞瀏覽器其他任務(dom構建,CSS渲染等),而加載內部是同步的(加載完模塊后立即執行回調)。

AMD也采用require命令加載模塊,但是不同于CommonJS,它要求兩個參數:

require([module], callback);

第一個參數[module],是一個數組,里面的成員是要加載的模塊,callback是加載完成后的回調函數。如果將上述的代碼改成AMD方式:

require(['math'], function(math) { math.add(2, 3);})

其中,回調函數中參數對應數組中的成員(模塊)。

requireJS加載模塊,采用的是AMD規范。也就是說,模塊必須按照AMD規定的方式來寫。

具體來說,就是模塊書寫必須使用特定的define()函數來定義。如果一個模塊不依賴其他模塊,那么可以直接寫在define()函數之中。

define(id?, dependencies?, factory);

id:模塊的名字,如果沒有提供該參數,模塊的名字應該默認為模塊加載器請求的指定腳本的名字;

dependencies:模塊的依賴,已被模塊定義的模塊標識的數組字面量。依賴參數是可選的,如果忽略此參數,它應該默認為 ["require", "exports", "module"]。然而,如果工廠方法的長度屬性小于3,加載器會選擇以函數的長度屬性指定的參數個數調用工廠方法。

factory:模塊的工廠函數,模塊初始化要執行的函數或對象。如果為函數,它應該只被執行一次。如果是對象,此對象應該為模塊的輸出值。

假定現在有一個math.js文件,定義了一個math模塊。那么,math.js書寫方式如下:

// math.jsdefine(function() { var add = function(x, y) { return x + y; } return { add: add }})

加載方法如下:

// main.jsrequire(['math'], function(math) { alert(math.add(1, 1));})

如果math模塊還依賴其他模塊,寫法如下:

// math.jsdefine(['dependenceModule'], function(dependenceModule) { // ...})

當require()函數加載math模塊的時候,就會先加載dependenceModule模塊。當有多個依賴時,就將所有的依賴都寫在define()函數第一個參數數組中,所以說AMD是依賴前置的。這不同于CMD規范,它是依賴就近的。

CMD

CMD推崇依賴就近,延遲執行??梢园涯愕囊蕾噷戇M代碼的任意一行,如下:

define(factory)

factory為函數時,表示是模塊的構造方法。執行該構造方法,可以得到模塊向外提供的接口。factory 方法在執行時,默認會傳入三個參數:require、exports 和 module.

// CMDdefine(function(require, exports, module) { var a = require('./a'); a.doSomething(); var b = require('./b'); b.doSomething();})

如果使用AMD寫法,如下:

// AMDdefine(['a', 'b'], function(a, b) { a.doSomething(); b.doSomething();})

這個規范實際上是為了Seajs的推廣然后搞出來的。那么看看SeaJS是怎么回事兒吧,基本就是知道這個規范了。

同樣Seajs也是預加載依賴js跟AMD的規范在預加載這一點上是相同的,明顯不同的地方是調用,和聲明依賴的地方。AMD和CMD都是用difine和require,但是CMD標準傾向于在使用過程中提出依賴,就是不管代碼寫到哪突然發現需要依賴另一個模塊,那就在當前代碼用require引入就可以了,規范會幫你搞定預加載,你隨便寫就可以了。但是AMD標準讓你必須提前在頭部依賴參數部分寫好(沒有寫好? 倒回去寫好咯)。這就是最明顯的區別。

sea.js通過sea.use()來加載模塊。

seajs.use(id, callback?)

UMD

由于CommonJS是服務器端的規范,跟AMD、CMD兩個標準實際不沖突。

當我們寫一個文件需要兼容不同的加載規范的時候怎么辦呢,看看下面的代碼。

(function (root, factory) { if (typeof define === 'function' && define.amd) { // AMD define(['jquery', 'underscore'], factory); } else if (typeof exports === 'object') { // Node, CommonJS之類的 module.exports = factory(require('jquery'), require('underscore')); } else { // 瀏覽器全局變量(root 即 window) root.returnExports = factory(root.jQuery, root._); }}(this, function ($, _) { // 方法 function a(){}; // 私有方法,因為它沒被返回 (見下面) function b(){}; // 公共方法,因為被返回了 function c(){}; // 公共方法,因為被返回了 // 暴露公共方法 return { b: b, c: c }}));

這個代碼可以兼容各種加載規范了。

ES6

es6通過import、export實現模塊的輸入輸出。其中import命令用于輸入其他模塊提供的功能,export命令用于規定模塊的對外接口。

export

一個模塊就是一個獨立的文件。該文件內部的所有變量,外部無法獲取。如果希望外部文件能夠讀取該模塊的變量,就需要在這個模塊內使用export關鍵字導出變量。如:

// PRofile.jsexport var a = 1;export var b = 2;export var c = 3;

下面的寫法是等價的,這種方式更加清晰(在底部一眼能看出導出了哪些變量):

var a = 1;var b = 2;var c = 3;export {a, b, c}

export命令除了輸出變量,還可以導出函數或類。

導出函數export function foo(){}function foo(){}function bar(){}export {foo, bar as bar2}

其中上面的as表示給導出的變量重命名。

要注意的是,export導出的變量只能位于文件的頂層,如果處于塊級作用域內,會報錯。如:

function foo() { export 'bar'; // SyntaxError}導出類export default class {} // 關于default下面會說

export語句輸出的值是動態綁定,綁定其所在的模塊。

// foo.jsexport var foo = 'foo';setTimeout(function() { foo = 'foo2';}, 500);// main.jsimport * as m from './foo';console.log(m.foo); // foosetTimeout(() => console.log(m.foo), 500); // foo2

import

import命令可以導入其他模塊通過export導出的部分。

// abc.jsvar a = 1;var b = 2;var c = 3;export {a, b, c}//main.jsimport {a, b, c} from './abc';console.log(a, b, c);

如果想為導入的變量重新取一個名字,使用as關鍵字(也可以在導出中使用)。

import {a as aa, b, c};console.log(aa, b, c)

如果想在一個模塊中先輸入后輸出一個模塊,import語句可以和export語句寫在一起。

import {a, b, c} form './abc';export {a, b, c}// 使用連寫, 可讀性不好,不建議export {a, b, c} from './abc';

模塊的整體加載

使用*關鍵字。

// abc.jsexport var a = 1;export var b = 2;export var c = 3;// main.jsimport * from as abc form './abc';console.log(abc.a, abc.b, abc.c);

export default

在export輸出內容時,如果同時輸出多個變量,需要使用大括號{},同時導入也需要大括號。使用export defalut輸出時,不需要大括號,而輸入(import)export default輸出的變量時,不需要大括號。

// abc.jsvar a = 1, b = 2, c = 3;export {a, b};export default c;import {a, b} from './abc';import c from './abc'; // 不需要大括號console.log(a, b, c) // 1 2 3

本質上,export default輸出的是一個叫做default的變量或方法,輸入這個default變量時不需要大括號。

// abc.jsexport {a as default};// main.jsimport a from './abc'; // 這樣也是可以的// 這樣也是可以的import {default as aa} from './abc';console.log(aa);

就到這里了吧。關于循環加載(模塊相互依賴)沒寫,CommonJS和ES6處理方式不一樣。

參考

該如何理解AMD ,CMD,CommonJS規范–javascript模塊化加載學習總結

AMD/CMD與前端規范

前端模塊化之旅(二):CommonJS、AMD和CMD

研究一下javascript的模塊規范(CommonJs/AMD/CMD)

Javascript模塊化編程(一):模塊的寫法

Javascript模塊化編程(二):AMD規范

Javascript模塊化編程(三):require.js的用法

Module


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产91在线高潮白浆在线观看| 91久久精品久久国产性色也91| 日本道色综合久久影院| 久久精品亚洲一区| 91精品国产综合久久久久久蜜臀| 欧美体内谢she精2性欧美| 亚洲天堂免费观看| 国产精品日本精品| 91亚洲精品一区二区| 日韩精品www| 久久久久久久久久久国产| 欧美电影第一页| 91久久在线观看| 成人在线精品视频| 欧美日韩激情网| 久久精品99无色码中文字幕| 亚洲一区二区国产| 岛国av一区二区在线在线观看| 亚洲免费福利视频| 91麻豆国产语对白在线观看| 国产成人精品在线观看| 国产精品a久久久久久| 国产日产欧美精品| 亚洲自拍小视频免费观看| 亚洲国产精品va在看黑人| 97在线观看免费高清| 欧美色xxxx| 亚洲经典中文字幕| 中文字幕亚洲自拍| 精品国产户外野外| 久久免费视频网| 亚洲www在线| 国内精品一区二区三区四区| 国产精品久久久久久久久久久久久| 国产欧美日韩中文字幕在线| 亚洲精品国产精品自产a区红杏吧| 57pao成人国产永久免费| 久久久久国色av免费观看性色| 久久精品中文字幕电影| 欧美一级成年大片在线观看| 欧美巨乳在线观看| 国产精品扒开腿做爽爽爽男男| 欧美一区第一页| 国产在线精品一区免费香蕉| 国产在线观看不卡| 欧美午夜视频在线观看| 91日本在线视频| 亚洲sss综合天堂久久| 国产一区二区三区在线| 夜夜狂射影院欧美极品| 成人免费观看网址| 日韩av中文字幕在线| 亚洲欧洲免费视频| 国产欧美精品一区二区三区介绍| 久久精品国产视频| 亚洲影视中文字幕| 欧美第一黄色网| 中文字幕亚洲综合久久筱田步美| 按摩亚洲人久久| 性欧美视频videos6一9| 综合欧美国产视频二区| 亚洲电影免费在线观看| 国产精品18久久久久久首页狼| 在线日韩欧美视频| 久久久久这里只有精品| 黑人巨大精品欧美一区二区免费| 国产成人综合精品在线| 成人黄色av网| 一区二区三区高清国产| 国产精品日韩专区| 国产精品www色诱视频| 亚洲欧美日韩中文视频| 国产精品99久久久久久久久| 欧美尤物巨大精品爽| 懂色av中文一区二区三区天美| 日韩免费av在线| 91av在线免费观看视频| 色噜噜狠狠狠综合曰曰曰88av| 久久久亚洲欧洲日产国码aⅴ| 性欧美xxxx视频在线观看| 成人欧美一区二区三区在线| 亚洲a级在线观看| 久久久之久亚州精品露出| 欧美日韩午夜视频在线观看| 欧美性开放视频| 久久久久久中文| 亚洲性猛交xxxxwww| 日本国产欧美一区二区三区| 亚洲一区av在线播放| 91国产精品电影| 黑人极品videos精品欧美裸| 亚洲精品日韩激情在线电影| 欧美另类老女人| 中文字幕日韩精品在线观看| 亚洲视频视频在线| 日本久久久久久久久| 欧美怡红院视频一区二区三区| 亚洲精品小视频| 国产福利成人在线| 精品偷拍一区二区三区在线看| 久久久久中文字幕| 欧美高跟鞋交xxxxxhd| 69久久夜色精品国产69乱青草| 久久免费福利视频| 日韩在线视频线视频免费网站| xxxx性欧美| 久久在线免费观看视频| 超碰精品一区二区三区乱码| 成人精品视频久久久久| 欧美性色视频在线| 国产精品女视频| 日韩美女视频在线观看| 欧美极品少妇与黑人| 国产精品黄页免费高清在线观看| 国产精品青青在线观看爽香蕉| 亚洲欧美三级在线| 中文字幕欧美日韩va免费视频| 日韩一级裸体免费视频| 中文字幕最新精品| 97色在线视频| 久久激情视频久久| 国产日韩欧美在线视频观看| 亚洲美女动态图120秒| 久久精品99久久久久久久久| 日韩欧美成人网| 中文字幕在线观看日韩| 一本大道久久加勒比香蕉| 最近2019免费中文字幕视频三| 欧美精品久久久久a| 国产精品欧美一区二区三区奶水| 欧美日韩国产一中文字不卡| 日韩大陆欧美高清视频区| 欧美激情xxxx| 欧美性色xo影院| 美女视频久久黄| 色老头一区二区三区在线观看| 亚洲男人天堂古典| 精品亚洲一区二区三区四区五区| 欧美在线www| 91po在线观看91精品国产性色| 国产精品久久久久久久久久三级| 国产精品对白刺激| 精品欧美激情精品一区| 最好看的2019年中文视频| 国产成人啪精品视频免费网| 日韩av电影国产| 国产精品女视频| 久久久久日韩精品久久久男男| 国产综合在线看| 欧美一级高清免费播放| 色黄久久久久久| 中文国产亚洲喷潮| 久久久成人的性感天堂| 亚洲欧美激情四射在线日| 国产精品中文字幕久久久| 久久久噜久噜久久综合| 色在人av网站天堂精品| 欧美最近摘花xxxx摘花| 欧美美最猛性xxxxxx| 亚洲天堂av综合网| 伊人男人综合视频网| 欧美性猛交xxxxx水多| 亚洲女性裸体视频| 日韩在线观看免费|