當(dāng)下, 我們幾乎所有的項(xiàng)目都是基于 webpack、rollup 等構(gòu)建工具進(jìn)行開發(fā)的,模塊化已經(jīng)是常態(tài)。
創(chuàng)新互聯(lián)公司:2013年至今為各行業(yè)開拓出企業(yè)自己的“網(wǎng)站建設(shè)”服務(wù),為上千余家公司企業(yè)提供了專業(yè)的成都網(wǎng)站制作、成都網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計(jì)和網(wǎng)站推廣服務(wù), 按需制作網(wǎng)站由設(shè)計(jì)師親自精心設(shè)計(jì),設(shè)計(jì)的效果完全按照客戶的要求,并適當(dāng)?shù)奶岢龊侠淼慕ㄗh,擁有的視覺效果,策劃師分析客戶的同行競爭對手,根據(jù)客戶的實(shí)際情況給出合理的網(wǎng)站構(gòu)架,制作客戶同行業(yè)具有領(lǐng)先地位的。
我們對它并不陌生,今天,我們就再系統(tǒng)的回顧一下ES6的模塊機(jī)制, 并總結(jié)下常用的操作和最佳實(shí)踐, 希望對你有所幫助。
一些簡單的背景
隨用隨取, 是一種我們都希望實(shí)現(xiàn)的機(jī)制。
在 Javascript 中也一樣,把一個大的 Javascript 程序分割成不同的部分, 哪個部分要被用到,就取那一部分。
在很長一段時間內(nèi), NodeJS 擁有這樣的能力, 后來, 越來越多的庫和框架也擁有了模塊化的能力, 比如 CommonJS, 或者基于AMD模型的實(shí)現(xiàn)(比如RequireJs),還有后續(xù)的Webpack, Babel等。
到2015年,一個標(biāo)準(zhǔn)的模塊化系統(tǒng)誕生了,這就是我們今天要說的主角 - ES6 模型系統(tǒng)。
一眼看上去, 我們不難發(fā)現(xiàn), ES6的模型系統(tǒng)和CommonJS語法非常的相似,畢竟ES6 的模型系統(tǒng)是從CommonJS時代走過來的, 深受CommonJS 影響。
看個簡單的例子,比如在CommonJs中: (https://flaviocopes.com/commonjs/)
//file.js
module.exports = value;
// 引入value
const value = require('file.js')而在ES6中:
// const.js
export const value = 'xxx';
import { value } from 'const.js'語法是非常相似的。
下面我們就主要看 import 和 export,和幾個相關(guān)的特性,了解ES6 Modules的更多方面。
模塊化的好處
模塊化的好處主要是兩點(diǎn):
1. 避免全局變量污染 2. 有效的處理依賴關(guān)系
隨著時代的演進(jìn), 瀏覽器原生也開始支持es6 import 和 export 語法了。

先看個簡單的例子:
<script type="module">
import { addTextToBody } from '/util.js';
addTextToBody('Modules are pretty cool.');
</script>
// util.js
export function addTextToBody(text) {
const p = document.createElement('p');
p.textContent = text;
document.body.appendChild(p);
}如果要處理事件,也是一樣, 看個簡單的例子:
<button id="test">Show Message</button>
<script type="module" crossorigin src="/showImport.js"></script>
// showImport.js
import { showMessage } from '/show.js'
document.getElementById('test').onclick = function() {
showMessage();
}
// show.js
export function showMessage() {
alert("Hello World!")
}如果你想跑這個demo, 注意要起個簡單的服務(wù):
$ http-server
否則,你會看到一個CORS拋錯。
至于拋錯的具體原因和其他細(xì)節(jié),不是本文討論的重點(diǎn), 感興趣的可以閱讀如下鏈接了解詳情。
https://jakearchibald.com/2017/es-modules-in-browsers/
嚴(yán)格模式
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode
'use strict' 聲明我們都不陌生, 在es5 時代我們也經(jīng)常使用, 一般是在文件頂部加這個聲明,目的就是禁用Javascript中不太友好的一部分,有助于我們寫更嚴(yán)謹(jǐn)?shù)拇a。
這個特性,在es6語法中是默認(rèn)開啟的, 如果代碼里面有不太嚴(yán)格的代碼,則會報錯,例如:

下面是我從MDN中摘取的一些在嚴(yán)格模式中被禁用的部分:
Variables can’t be left undeclaredFunction parameters must have unique names (or are considered syntax errors)with is forbiddenread-only propertiesOctal numbers like 00840 are syntax errorsdelete undeletable properties throw an errordelete prop is a syntax error, instead of assuming delete global[prop]eval doesn’t introduce new variables into its surrounding scopeeval and arguments can’t be bound or assigned toarguments doesn’t magically track changes to method parametersarguments.callee throws a TypeError, no longer supportedarguments.caller throws a TypeError, no longer supportedfn.caller and fn.arguments to access the JavaScript stackReserved words (e.g protected, static, interface, etc) cannot be boundexports 的幾種用法
ES6模塊只支持靜態(tài)導(dǎo)出,你只可以在模塊的最外層作用域使用export,不可在條件語句中使用,也不能在函數(shù)作用域中使用。
從分類上級講, exports 主要有三種:
1、Named Exports (Zero or more exports per module)
2、Default Exports (One per module)
3、Hybrid Exports
exports 總覽:
// Exporting inpidual features
export let name1, name2, …, nameN; // also var, const
export let name1 = …, name2 = …, …, nameN; // also var, const
export function functionName(){...}
export class ClassName {...}
// Export list
export { name1, name2, …, nameN };
// Renaming exports
export { variable1 as name1, variable2 as name2, …, nameN };
// Exporting destructured assignments with renaming
export const { name1, name2: bar } = o;
// Default exports
export default expression;
export default function (…) { … } // also class, function*
export default function name1(…) { … } // also class, function*
export { name1 as default, … };
// Aggregating modules
export * from …; // does not set the default export
export * as name1 from …;
export { name1, name2, …, nameN } from …;
export { import1 as name1, import2 as name2, …, nameN } from …;
export { default } from …;下面我就介紹一下常見的 exports用法。
1. Named exports (導(dǎo)出每個函數(shù)/變量)
具名導(dǎo)出,這種方式導(dǎo)出多個函數(shù),一般使用場景比如 utils、tools、common 之類的工具類函數(shù)集,或者全站統(tǒng)一變量等。
只需要在變量或函數(shù)前面加 export 關(guān)鍵字即可。
//------ lib.js ------
export const sqrt = Math.sqrt;
export function square(x) {
return x * x;
}
export function diag(x, y) {
return sqrt(square(x) + square(y));
}
//------ main.js 使用方式1 ------
import { square, diag } from 'lib';
console.log(square(11)); // 121
console.log(diag(4, 3)); // 5
//------ main.js 使用方式2 ------
import * as lib from 'lib';
console.log(lib.square(11)); // 121
console.log(lib.diag(4, 3)); // 5我們也可以直接導(dǎo)出一個列表,例如上面的lib.js可以改寫成:
//------ lib.js ------
const sqrt = Math.sqrt;
function square(x) {
return x * x;
}
function add (x, y) {
return x + y;
}
export { sqrt, square, add }2. Default exports (導(dǎo)出一個默認(rèn) 函數(shù)/類)
這種方式比較簡單,一般用于一個類文件,或者功能比較單一的函數(shù)文件使用。
一個模塊中只能有一個export default默認(rèn)輸出。
export default與export的主要區(qū)別有兩個:
不需要知道導(dǎo)出的具體變量名, 導(dǎo)入(import)時不需要{}.
//------ myFunc.js ------
export default function () {};
//------ main.js ------
import myFunc from 'myFunc';
myFunc();導(dǎo)出一個類
//------ MyClass.js ------
class MyClass{}
export default MyClass;
//------ Main.js ------
import MyClass from 'MyClass';注意這里默認(rèn)導(dǎo)出不需要用{}。
3. Mixed exports (混合導(dǎo)出)
混合導(dǎo)出,也就是 上面第一點(diǎn)和第二點(diǎn)結(jié)合在一起的情況。比較常見的比如 Lodash,都是這種組合方式。
//------ lib.js ------
export var myVar = ...;
export let myVar = ...;
export const MY_CONST = ...;
export function myFunc() {
// ...
}
export function* myGeneratorFunc() {
// ...
}
export default class MyClass {
// ...
}
// ------ main.js ------
import MyClass, { myFunc } from 'lib';再比如lodash例子:
//------ lodash.js ------
export default function (obj) {
// ...
};
export function each(obj, iterator, context) {
// ...
}
export { each as forEach };
//------ main.js ------
import _, { forEach } from 'lodash';4. Re-exporting (別名導(dǎo)出)
一般情況下,export輸出的變量就是在原文件中定義的名字,但也可以用 as 關(guān)鍵字來指定別名,這樣做一般是為了簡化或者語義化export的函數(shù)名。
//------ lib.js ------
export function getUserName(){
// ...
};
export function setName(){
// ...
};
//輸出別名,在import的時候可以同時使用原始函數(shù)名和別名
export {
getName as get, //允許使用不同名字輸出兩次
getName as getNameV2,
setName as set
}5. Module Redirects (中轉(zhuǎn)模塊導(dǎo)出)
有時候?yàn)榱吮苊馍蠈幽K導(dǎo)入太多的模塊,我們可能使用底層模塊作為中轉(zhuǎn),直接導(dǎo)出另一個模塊的內(nèi)容如下:
//------ myFunc.js ------
export default function() {...};
//------ lib.js ------
export * from 'myFunc';
export function each() {...};
//------ main.js ------
import myFunc, { each } from 'lib';
export 只支持在最外層靜態(tài)導(dǎo)出、只支持導(dǎo)出變量、函數(shù)、類,如下的幾種用法都是錯誤的。
`錯誤`的export用法:
//直接輸出變量的值
export 'Mark';
// 未使用中括號 或 未加default
// 當(dāng)只有一個導(dǎo)出數(shù),需加default,或者使用中括號
var name = 'Mark';
export name;
//export不要輸出塊作用域內(nèi)的變量
function () {
var name = 'Mark';
export { name };
}import的幾種用法
import的用法和export是一一對應(yīng)的,但是import支持靜態(tài)導(dǎo)入和動態(tài)導(dǎo)入兩種方式,動態(tài)import支持晚一些,兼容性要差一些。

下面我就總結(jié)下import的基本用法:
1. Import All things
當(dāng)export有多個函數(shù)或變量時,如文中export的第一點(diǎn),可以使用 * as 關(guān)鍵字來導(dǎo)出所有函數(shù)及變量,同時 as 后面跟著的名稱做為 該模塊的命名空間。
//導(dǎo)出lib的所有函數(shù)及變量 import * as lib from 'lib'; //以 lib 做為命名空間進(jìn)行調(diào)用,類似于object的方式 console.log(lib.square(11)); // 121
2. Import a single/multiple export from a module
從模塊文件中導(dǎo)入單個或多個函數(shù),與 * as namepage 方式不同,這個是按需導(dǎo)入。如下例子:
//導(dǎo)入square和 diag 兩個函數(shù)
import { square, diag } from 'lib';
// 只導(dǎo)入square 一個函數(shù)
import { square } from 'lib';
// 導(dǎo)入默認(rèn)模塊
import _ from 'lodash';
// 導(dǎo)入默認(rèn)模塊和單個函數(shù),這樣做主要是簡化單個函數(shù)的調(diào)用
import _, { each } from 'lodash';3. Rename multiple exports during import
和 export 一樣,也可以用 as 關(guān)鍵字來設(shè)置別名,當(dāng)import的兩個類的名字一樣時,可以使用 as 來重設(shè)導(dǎo)入模塊的名字,也可以用as 來簡化名稱。
比如:
// 用 as 來 簡化函數(shù)名稱
import {
reallyReallyLongModuleExportName as shortName,
anotherLongModuleName as short
} from '/modules/my-module.js';
// 避免重名
import { lib as UserLib} from "alib";
import { lib as GlobalLib } from "blib";4. Import a module for its side effects only
有時候我們只想import一個模塊進(jìn)來,比如樣式,或者一個類庫。
// 導(dǎo)入樣式 import './index.less'; // 導(dǎo)入類庫 import 'lodash';
5. Dynamic Imports
靜態(tài)import在首次加載時候會把全部模塊資源都下載下來.
我們實(shí)際開發(fā)時候,有時候需要動態(tài)import(dynamic import)。
例如點(diǎn)擊某個選項(xiàng)卡,才去加載某些新的模塊:
// 當(dāng)動態(tài)import時,返回的是一個promise
import('lodash')
.then((lodash) => {
// Do something with lodash.
});
// 上面這句實(shí)際等同于
const lodash = await import('lodash');es7的新用法:
async function run() {
const myModule = await import('./myModule.js');
const { export1, export2 } = await import('./myModule.js');
const [module1, module2, module3] =
await Promise.all([
import('./module1.js'),
import('./module2.js'),
import('./module3.js'),
]);
}
run();以上就是詳解ES6 Modules的詳細(xì)內(nèi)容,更多請關(guān)注創(chuàng)新互聯(lián)其它相關(guān)文章!
網(wǎng)站題目:ECMAScript6中Modules的用法
URL地址:http://chinadenli.net/article10/gogodo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供電子商務(wù)、網(wǎng)站設(shè)計(jì)、網(wǎng)站營銷、動態(tài)網(wǎng)站、定制開發(fā)、面包屑導(dǎo)航
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)