Js模塊化導入導出


Js模塊化導入導出

CommonJsAMDCMDES6都是用於模塊化定義中使用的規范,其為了規范化模塊的引入與處理模塊之間的依賴關系以及解決命名沖突問題,並使用模塊化方案來使復雜系統分解為代碼結構更合理,可維護性更高的可管理的模塊。

CommonJS

CommonJSNodeJs服務器端模塊的規范,根據這個規范,每個文件就是一個模塊,有自己的作用域。在一個文件里面定義的變量、函數、類,都是私有的,對其他文件不可見。CommonJS規范規定,每個模塊內部,module變量代表當前模塊。這個變量是一個對象,它的exports屬性是對外的接口。加載某個模塊,其實是加載該模塊exports屬性。總之,CommonJS規范通過require導入,module.exportsexports進行導出。

// 1.js
var a  = 1;
var b = function(){
    console.log(a);
}

module.exports = {
    a: a,
    b: b
}

/*
// 當導出的模塊名與被導出的成員或方法重名時可以有如下寫法
module.exports = {
    a,
    b
}
*/
// 2.js
var m1 = require("./1.js")

console.log(m1.a); // 1
m1.b(); // 1

也可以使用exports進行導出,但一定不要重寫exports的指向,因為exports只是一個指針並指向module.exports的內存區域,即exports = module.exports = {},重寫exports則改變了指針指向將導致模塊不能導出,簡單來說exports就是為寫法提供了一個簡便方案,最后其實都是利用module.exports導出。此外若是在一個文件中同時使用module.exportsexports,則只會導出module.exports的內容

// 1.js
var a  = 1;
var b = function(){
    console.log(a);
}

exports.a = a;
exports.b = b;

// exports = { a, b } // 不能這么寫,這樣就改變了exports的指向為一個新對象而不是module.exports
// 2.js
var m1 = require("./1.js")

console.log(m1.a); // 1
m1.b(); // 1

AMD

AMD規范不是AMD YESAMD異步模塊定義,全稱Asynchronous Module Definition規范,是瀏覽器端的模塊化解決方案,CommonJS規范引入模塊是同步加載的,這對服務端不是問題,因為其模塊都存儲在硬盤上,可以等待同步加載完成,但在瀏覽器中模塊是通過網絡加載的,若是同步阻塞等待模塊加載完成,則可能會出現瀏覽器頁面假死的情況,AMD采用異步方式加載模塊,模塊的加載不影響它后面語句的運行。所有依賴這個模塊的語句,都定義在一個回調函數中,等到加載完成之后,這個回調函數才會運行,RequireJS就是實現了AMD規范。

require(['moduleA', 'moduleB', 'moduleC'], function (moduleA, moduleB, moduleC){
    // do something
});

define(['moduleA', 'moduleB', 'moduleC'], function (moduleA, moduleB, moduleC){
    // do something
    return {};
});

/**
define和require在依賴處理和回調執行上都是一樣的,不一樣的地方是define的回調函數需要有return語句返回模塊對象(注意是對象),這樣define定義的模塊才能被其他模塊引用;require的回調函數不需要return語句,無法被別的模塊引用
*/

// html的<script>標簽也支持異步加載
// <script src="require.js" defer async="true" ></script> <!-- async屬性表明這個文件需要異步加載,避免網頁失去響應。IE不支持這個屬性,只支持defer,所以把defer也寫上。 -->

CMD

CMD通用模塊定義,是SeaJS在推廣過程中對模塊定義的規范化產出,也是瀏覽器端的模塊化異步解決方案,CMDAMD的區別主要在於:

  • 對於依賴的模塊,AMD是提前執行(相對定義的回調函數, AMD加載器是提前將所有依賴加載並調用執行后再執行回調函數),CMD是延遲執行(相對定義的回調函數, CMD加載器是將所有依賴加載后執行回調函數,當執行到需要依賴模塊的時候再執行調用加載的依賴項並返回到回調函數中),不過RequireJS2.0開始,也改成可以延遲執行
  • AMD是依賴前置(在定義模塊的時候就要聲明其依賴的模塊),CMD是依賴就近(只有在用到某個模塊的時候再去require——按需加載,即用即返)。
define(function(require,exports,module){
  var a = reuire('require.js');
  a.dosomething();
  return {};
});

ES6

ES6在語言標准的層面上實現了模塊的功能,是為了成為瀏覽器和服務器通用的模塊解決方案,ES6標准使用exportexport default來導出模塊,使用import導入模塊。此外在瀏覽器環境中是可以使用require來導入exportexport default導出的模塊的,但依然建議使用import標准導入模塊。
exportexport default主要有以下區別:

  • export能按需導入,export default不行。
  • export可以有多個,export default僅有一個。
  • export能直接導出變量表達式,export default不行。
  • export方式導出,在導入時要加{}export default則不需要。
// 導出單個特性
export let name1, name2, …, nameN; // also var, const
export let name1 = …, name2 = …, …, nameN; // also var, const
export function FunctionName(){...}
export class ClassName {...}

// 導出列表
export { name1, name2, …, nameN };

// 重命名導出
export { variable1 as name1, variable2 as name2, …, nameN };

// 解構導出並重命名
export const { name1, name2: bar } = o;

// 默認導出
export default expression;
export default function (…) { … } // also class, function*
export default function name1(…) { … } // also class, function*
export { name1 as default, … };

// 導出模塊合集
export * from …; // does not set the default export
export * as name1 from …; // Draft ECMAScript® 2O21
export { name1, name2, …, nameN } from …;
export { import1 as name1, import2 as name2, …, nameN } from …;
export { default } from …;
// name-從將要導入模塊中收到的導出值的名稱
// member, memberN-從導出模塊,導入指定名稱的多個成員
// defaultMember-從導出模塊,導入默認導出成員
// alias, aliasN-別名,對指定導入成員進行的重命名
// module-name-要導入的模塊。是一個文件名
// as-重命名導入成員名稱(“標識符”)
// from-從已經存在的模塊、腳本文件等導入
import defaultMember from "module-name";
import * as name from "module-name";
import { member } from "module-name";
import { member as alias } from "module-name";
import { member1 , member2 } from "module-name";
import { member1 , member2 as alias2 , [...] } from "module-name";
import defaultMember, { member [ , [...] ] } from "module-name";
import defaultMember, * as name from "module-name";
import "module-name"; // 將運行模塊中的全局代碼, 但實際上不導入任何值。
// 1.js
var a  = 1;
var b = function(){
    console.log(a);
}

var c = 3;
var d = a + c;

var obj = { a,b,c }



export {a,b};

export {c,d};

export default obj;
<!-- 3.html 由於瀏覽器限制,需要啟動一個server服務 -->
<!DOCTYPE html>
<html>
<head>
    <title>ES6</title>
</head>
<body>

</body>
<script type="module">
    import {a,b} from "./1.js"; // 導入export
    import m1 from "./1.js"; // 不加{}即導入export default 
    import {c} from "./1.js"; // 導入export 按需導入
    
    console.log(a); // 1
    console.log(b); // ƒ (){ console.log(a); }
    console.log(m1); // {a: 1, c: 3, b: ƒ}
    console.log(c); // 3
</script>
</html>

每日一題

https://github.com/WindrunnerMax/EveryDay

參考

https://segmentfault.com/a/1190000010426778
https://www.cnblogs.com/leftJS/p/11073481.html
https://www.cnblogs.com/zhoulujun/p/9415407.html
https://www.cnblogs.com/zhoulujun/p/9415407.html
https://www.cnblogs.com/moxiaowohuwei/p/8692359.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM