JavaScript?模塊化詳解
前言:
1.概念
- 將一個(gè)復(fù)雜的程序依據(jù)一定的規(guī)則(規(guī)范)封裝成幾個(gè)塊(文件), 并進(jìn)行組合在一起;
- 塊的內(nèi)部數(shù)據(jù)與實(shí)現(xiàn)是私有的, 只是向外部暴露一些接口(方法)與外部其它模塊通信。
2.模塊化的好處
- 避免命名沖突(減少命名空間污染);
- 更好的分離, 按需加載;
- 更高復(fù)用性;
- 更高可維護(hù)性。
3.引入多個(gè)script標(biāo)簽后出現(xiàn)的問(wèn)題
- 請(qǐng)求過(guò)多(依賴的模塊過(guò)多,請(qǐng)求就會(huì)過(guò)多);
- 依賴模糊(不知道模塊的具體依賴關(guān)系,導(dǎo)致加載順序出錯(cuò));
- 難以維護(hù)(以上兩個(gè)原因就會(huì)造成這個(gè)結(jié)果)。
//index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="jQuery.js"></script> <script src="module.js"></script> </head> <body> <div>123</div> </body> <script> myModule.foo(); myModule.bar(); console.log(myModule.data) ; myModule.data = 'xxxx'; myModule.foo(); </script> </html>
//module.js IIFE(匿名函數(shù)自調(diào)用)
;(function(window,$){
let data = "www.baidu.com";
function foo() {
console.log(`foo() ${data}`);
//這里需要使用jQuery庫(kù)
$('body').css('background', 'red')
}
function bar() {
console.log(`bar() ${data}`);
otherFun();
}
function otherFun() {
console.log(`otherFun()`);
}
window.myModule = { foo, bar };
})(window, jQuery)
一、CommonJS
- NODE 就是基于
commonJS模塊規(guī)范,每一個(gè)文件就是一個(gè)模塊;有自己的作用域;在服務(wù)器端,模塊的加載是同步的;在瀏覽器端,模塊需提前編譯打包處理
特點(diǎn):
- 所有代碼都運(yùn)行在模塊作用域,不會(huì)污染全局作用域;
- 模塊可以多次加載,但是只會(huì)在第一次加載時(shí)運(yùn)行一次,然后運(yùn)行結(jié)果就被緩存了,以后再加載,就直接讀取緩存結(jié)果。要想讓模塊再次運(yùn)行,必須清除緩存。
- 模塊加載的順序,按照其在代碼中出現(xiàn)的順序。
語(yǔ)法:
- 暴露模塊:
js module.exports = value或者js exports.xxx = value - 引入模塊:
js require('xxx')如果是第三方模塊,xxx為模塊名;如果是自定義模塊,xxx為模塊文件路徑
CommonJS規(guī)范規(guī)定,每個(gè)模塊內(nèi)部,module變量代表當(dāng)前模塊。這個(gè)變量是一個(gè)對(duì)象,它的exports屬性(即module.exports)是對(duì)外的接口。加載某個(gè)模塊,其實(shí)是加載該模塊的module.exports屬性。
require命令用于加載模塊文件。require命令的基本功能是,讀入并執(zhí)行一個(gè)JavaScript文件,然后返回該模塊的exports對(duì)象。如果沒(méi)有發(fā)現(xiàn)指定模塊,會(huì)報(bào)錯(cuò)。
CommonJS模塊的加載機(jī)制是,輸入的是被輸出的值的拷貝。也就是說(shuō),一旦輸出一個(gè)值,模塊內(nèi)部的變化就影響不到這個(gè)值
二、AMD
- 相比于CommonJS的同步加載模塊,AMD更適合于瀏覽器端的非同步模塊加載,因?yàn)锳MD允許指定回調(diào)函數(shù)
- 目錄結(jié)構(gòu)

使用require.js
<!-- index.html --> <script src="https://cdn.bootcdn.net/ajax/libs/require.js/2.3.6/require.js"></script>
//定義一個(gè)沒(méi)有依賴的module1模塊
define('module1', () => {
let count = 0;
const add = () => ++ count;
const reset = () => count = 0;
const upperCase = string => string.toUpperCase()
return {
add,
reset,
upperCase
}
})
//定義一個(gè)有依賴的module2模塊,依賴module1
define('module2',['module1'], (module1) => {
const showMsg = () => module1.upperCase('hello-amd');
return {
showMsg
}
})
<!-- 在html文件中使用模塊 -->
<body>
<script>
require.config({
paths: {
module1: './modules/module1',
module2: './modules/module2'
}
})
require(['module1', 'module2'], (module1, module2) => {
console.log(module1.add()) // 1
console.log(module1.reset()) //0
console.log(module2.showMsg()) //HELLO-AMD
})
</script>
</body>
三、CMD
- CMD集CommonJS與AMD的優(yōu)點(diǎn)于一身,cmd 規(guī)范專門用于瀏覽器端,模塊的加載是異步的,模塊使用時(shí)才會(huì)加載執(zhí)行(實(shí)現(xiàn)了按需加載,而AMD是不支持按需加載的)
- 目錄結(jié)構(gòu)

使用sea.js
<script src="https://cdn.bootcdn.net/ajax/libs/seajs/3.0.3/sea.js"></script>
//定義模塊module1
define((require, exports, module) => {
let string = 'I am a string';
const readString = () => 'module1 show() ' + string;
//向外暴露
exports.readString = readString;
})
//定義模塊module2
define((require, exports, module) => {
exports.msg = "正是在下啊"
})
//定義模塊module
define((require, exports, module) => {
//引入依賴模塊(同步)
var module1 = require('./module1');
console.log(module1.readString()) // module1 show() I am a string
//引入依賴模塊(異步)
require.async('./module2', md2 => {
console.log(`這是異步引入的:${md2.msg}`) //這是異步引入的:正是在下啊
})
})
<!-- html文件使用module -->
<body>
<script>
seajs.use('./modules/module')
</script>
四、ES6模塊化
ES6 模塊的設(shè)計(jì)思想是盡量的靜態(tài)化,使得編譯時(shí)就能確定模塊的依賴關(guān)系,以及輸入和輸出的變量。CommonJS 和 AMD 模塊,都只能在運(yùn)行時(shí)確定這些東西。
兩個(gè)關(guān)鍵字 import和export
- import 導(dǎo)入
- export 導(dǎo)出
//mian.js
export default {
showMsg() {
console.log('hahahahahah')
}
}
export const msg = "正是花好月圓時(shí)!"
//index.js
import module1 from "./module1"; //對(duì)應(yīng)export default
module1.showMsg()
import { msg } from './module1'; //對(duì)應(yīng)export
console.log(msg)
/*tips: 不要在html里使用<script type="module">
import ....., 有跨域問(wèn)題,可以在vscode里下載一個(gè)插件,或者本地起服務(wù)都可以解決,就不贅述了。
</script>*/
到此這篇關(guān)于JavaScript 模塊化詳解的文章就介紹到這了,更多相關(guān)JavaScript 模塊化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript中值類型與引用類型實(shí)例說(shuō)明
JavaScript中值類型與引用類型說(shuō)明,需要的朋友可以參考下。2010-12-12
javascript substr和substring用法比較
在js中substring和substr都是用來(lái)截取字符串的,那么substring和substr之間的具體區(qū)別在哪里,有沒(méi)有區(qū)別呢,下面我來(lái)給各位詳細(xì)引用一些實(shí)例來(lái)介紹這些問(wèn)題2009-06-06
js之如何刪除多層數(shù)組嵌套的最后一層中的部分?jǐn)?shù)據(jù)
這篇文章主要介紹了js之如何刪除多層數(shù)組嵌套的最后一層中的部分?jǐn)?shù)據(jù)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06
詳解JavaScript的Date對(duì)象(制作簡(jiǎn)易鐘表)
這篇文章主要為大家詳細(xì)介紹了JavaScript的Date對(duì)象,和大家分享如何制作簡(jiǎn)易鐘表,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2015-12-12
使用純JS實(shí)現(xiàn)checkbox的框選效果(鼠標(biāo)拖拽多選)
最近做了一個(gè)用js實(shí)現(xiàn)鼠標(biāo)拖拽多選的功能,于是整理了一下思路,寫了一個(gè)小demo,下面這篇文章主要給大家介紹了關(guān)于如何使用純JS實(shí)現(xiàn)checkbox的框選效果(鼠標(biāo)拖拽多選)的相關(guān)資料,需要的朋友可以參考下2022-05-05
不用typsescript如何使用類型增強(qiáng)功能
這篇文章主要給大家介紹了關(guān)于不用typsescript如何使用類型增強(qiáng)功能的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03

