溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

js中常用模塊化方案有哪些

發(fā)布時間:2020-10-28 11:04:01 來源:億速云 閱讀:161 作者:小新 欄目:web開發(fā)

這篇文章給大家分享的是有關(guān)js中常用模塊化方案有哪些的內(nèi)容。小編覺得挺實用的,因此分享給大家做個參考。一起跟隨小編過來看看吧。

                                                           本篇文章給大家?guī)淼膬?nèi)容是關(guān)于為什么需要模塊化?js中常用模塊化方案介紹,有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。

為什么需要模塊化

在ES6出現(xiàn)之前,JS語言本身并沒有提供模塊化能力,這為開發(fā)帶來了一些問題,其中最重要的兩個問題應(yīng)當(dāng)是全局污染和依賴管理混亂。

// file a.js
var name = 'aaa';
var sayName = function() {
    console.log(name);
};
<!-- file index.html -->
<script src='xxx/xxx/a.js'></script>

<script>
    sayName(); // 'aaa'
    
    // code...
    
    var name = 'bbb';
    
    sayName(); // 'bbb'
</script>

上面的代碼中,我們兩次調(diào)用a.js所提供的sayName函數(shù)輸出了不同結(jié)果,很明顯這是因為兩個文件都對變量name進行了賦值,因此相互之間造成了影響。當(dāng)然我們可以在編寫代碼時注意不要定義已存在的變量名,但是當(dāng)一個頁面引用了10幾個幾百行的文件時,記住所有已經(jīng)定義過的變量顯然不太現(xiàn)實。

// file a.js
var name = getName();
var sayName = function() {
    console.log(name)
};
// file b.js
var getName = function() {
    return 'timo';
};
<script src='xxx/xxx/b.js'></script>
<script src='xxx/xxx/a.js'></script>

<script>
    sayName(); // 'timo'
</script>
<script src='xxx/xxx/a.js'></script>
<script src='xxx/xxx/b.js'></script>

// Uncaught ReferenceError: getName is not defined

上面的代碼說明,多個文件有依賴關(guān)系時,我們需要確保其引入的順序,從而保證運行某個文件時,其依賴已經(jīng)提前加載,可以想象,面對越大型的項目,我們需要處理的依賴關(guān)系也就越多,這既麻煩又容易出錯。

而為了解決這些,社區(qū)中出現(xiàn)了許多為JS語言提供模塊化能力的規(guī)范,借助這些規(guī)范,能讓我們的開發(fā)更加方便安全。

常見模塊化方案

CommonJS

CommonJS是由社區(qū)提出的模塊化方案中的一種,Node.js遵循了這套方案。

基本寫法
// file a.js
var obj = {
    sayHi: function() {
        console.log('I am timo');
    };
};

module.exports obj;
// file b.js
var Obj = require('xxx/xxx/a.js');

Obj.sayHi(); // 'I am timo'

上面的代碼中,文件a.js是模塊的提供方,文件b.js是模塊調(diào)用方。

規(guī)范
  1. 每個文件都是一個模塊;

  2. 在模塊內(nèi)提供module對象,表示當(dāng)前模塊;

  3. 模塊使用exports對外暴露自身的函數(shù)/對象/變量等;

  4. 模塊內(nèi)通過require()方法導(dǎo)入其他模塊;

CommonJS的規(guī)范,簡單來說就是上面4條,可以對照基本寫法中的例子理解一下,在實際實現(xiàn)中,Node.js雖然遵循CommonJS規(guī)范,但是仍然對其進行了一些調(diào)整。

AMD

AMD是模塊化規(guī)范中的一種,RequireJS遵循了這套規(guī)范。

基本用法
 // file a.js
 define('module', ['m', './xxx/n.js'], function() {
    // code...
 })

上面的代碼中,文件a.js向外導(dǎo)出了模塊;

規(guī)范

AMD中,暴露模塊使用define函數(shù)

define(moduleName, [], callback);

如上面代碼,define函數(shù)共有三個參數(shù)

  • moduleName該參數(shù)可以省略,表示該模塊的名字,一般作用不大

  • ['name1', 'name2'],第二個參數(shù)是一個數(shù)組,表示當(dāng)前模塊依賴的其他模塊,如果沒有依賴模塊,該參數(shù)可以省略

  • callback,第三個參數(shù)是必傳參數(shù),是一個回調(diào)函數(shù),內(nèi)部是當(dāng)前模塊的相關(guān)代碼

其他

ADM的特點是依賴前置,這是ADM規(guī)范與接下來要介紹的CMD規(guī)范最大的不同,依賴前置是指:在運行當(dāng)前加載模塊回調(diào)前,會首先將所有依賴包加載完畢,也是就是define函數(shù)的第二個參數(shù)中指定的依賴包。

CDM

基本寫法
 define(function(require, exports, module) {   
    var a = require('./a')  
    a.doSomething();
    // code... 
    var b = require('./b') 
    // code...
})

上面代碼是CMD規(guī)范導(dǎo)出模塊的基本寫法;

規(guī)范

從寫法可以看出,CMD的寫法和AMD非常像,其主要區(qū)別是對于依賴加載時機的不同,上面已經(jīng)說過,AMD是依賴前置,而CMD規(guī)范推崇就近原則,簡單說就是在模塊運行前并不加載依賴,模塊運行過程中,當(dāng)需要某個依賴時,再去進行加載。

UMD

CommonJS、AMD、CMD并行的狀態(tài)下,就需要一種方案能夠兼容他們,這樣我們在開發(fā)時,就不需要再去考慮依賴模塊所遵循的規(guī)范了,而UMD的出現(xiàn)就是為了解決這個問題。

基本寫法
(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        //AMD
        define(['jquery'], factory);
    } else if (typeof exports === 'object') {
        //Node, CommonJS之類的
        module.exports = factory(require('jquery'));
    } else {
        //瀏覽器全局變量(root 即 window)
        root.returnExports = factory(root.jQuery);
    }
}(this, function ($) {
    //方法
    function myFunc(){};
    //暴露公共方法
    return myFunc;
}));

上面的代碼是UMD的基本寫法,從代碼就可以看出,其能夠同時支持CommonJS規(guī)范和AMD規(guī)范。

ES6 module

上面分別介紹了CommonJS、AMD、CMD和UMD,他們都是社區(qū)對于JS實現(xiàn)模塊化的貢獻,這個規(guī)范其產(chǎn)生的根本原因,都是JS語言自身沒有模塊化能力,而目前,在JS最新的語言規(guī)范ES6中,已經(jīng)為JS增加了模塊化能力,而JS自身的模塊化方案,完全能夠替代目前社區(qū)提出的各類規(guī)范,且能夠做到瀏覽器端和Node端通用。

ES6中的模塊化能力由兩個命令構(gòu)成:exportimport,export命令用于規(guī)定模塊的對外接口,import命令用于輸入其他模塊提供的功能。

export命令

ES6中一個文件就是一個模塊,模塊內(nèi)部的變量/函數(shù)等外部是無法訪問的,如果希望將內(nèi)部的函數(shù)/變量等對外暴露,供其他模塊進行使用,就需要通過export命令進行導(dǎo)出

// file a.js
export let a = 1;
export let b = 2;
export let c = 3;
// file b.js
let a = 1;
let b = 2;
let c = 3;

export {a, b, c}
// file c.js
export let add = (a, b) => {
    return a + b;
};

上面三個文件的代碼,都是通過export命令導(dǎo)出模塊內(nèi)容的示例,其中a.js文件和b.js文件都是導(dǎo)出模塊中的變量,作用完全一致但寫法不同,一般我們更推薦b.js文件中的寫法,原因是這種寫法能夠在文件最底部清楚地知道當(dāng)前模塊都導(dǎo)出了哪些變量。

import命令

模塊通過export命令導(dǎo)出變量/函數(shù)等,是為了讓其他模塊能夠?qū)肴ナ褂?,在ES6中,文件導(dǎo)入其他模塊是通過import命令進行的

// file d.js
import {a, b, c} from './a.js';

上面的代碼中,我們引入了a.js文件中的變量a、b、c,import在引入其他模塊內(nèi)的函數(shù)/變量時,必須與原模塊所暴露出來的函數(shù)名/變量名一一對應(yīng)。
同時,import命令引入的值是只讀的,如果嘗試對其進行修改,則會報錯

import {a} d from './a.js';
a = 2; // Syntax Error : 'a' is read-only;
export default命令

從上面import的介紹可以看到,當(dāng)需要引入其他模塊時,需要知道此模塊暴露出的變量名/函數(shù)名才可以,這顯然有些麻煩,因此ES6還提供了一個import default命令

// file a.js

let add = (a, b) => {
    return a+b
};
export default add;
// file b.js
import Add from './a.js';

Add(1, 2); // 3

上面的代碼中,a.js通過export default命令導(dǎo)出了add函數(shù),在b.js文件中引入時,可以隨意指定其名稱

export default命令是默認導(dǎo)出的意思,既然是默認導(dǎo)出,顯然只能有一個,因此每個模塊只能執(zhí)行一次export default命令,其本質(zhì)是導(dǎo)出了一個名為default的變量或函數(shù)。

感謝各位的閱讀!關(guān)于js中常用模塊化方案有哪些就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI