ES6之路之模塊詳解

迎接接見
個人站點

簡介

作甚模塊

一個模塊只不過是一個寫在文件中的 JavaScript 代碼塊。

模塊中的函數或變量不可用,除非模塊文件導出它們。

簡樸地說,這些模塊能夠協助你在你的模塊中編寫代碼,而且只公然應當被你的代碼的其他部份接見的代碼部份。

為何要運用模塊

  1. 增添可保護性:由於每一個模塊都是自力的,每一個人寫的代碼是不會相互影響的,在保護代碼的時刻很好排查是哪一個模塊失足。
  2. 可復用性:在一樣平常的開闢中,特別是大點的項目,代碼的可復用性就更重要了,或許你會用複製粘貼的情勢,然則直接一個 import 敕令就能夠搞定,豈不快哉。
  3. 防止定名污染:在 javascript 劇本中,一切的 js 文件的頂級作用域建立的變量,會被添加到同享的全局作用域,這就會致使差別的人開闢的代碼能夠會有雷同的變量名,致使變量名污染。

怎樣運用

導出模塊

導出模塊所用的敕令是 export。

前面也提到一個模塊就是一個 javascript 文件,在這個模塊中定義的變量,外部是沒法獲取到的,只要經由過程 export 導出的變量其他模塊才能夠用

最簡樸的導出體式格局就是在聲明的變量、函數、類前面加一個 export

// export1.js 

// 導出變量
export let name = '桃翁';

// 導出函數
export function print() {
    console.log("迎接關注民眾號:前端桃園");
}

// 導出類
export class Person {
    constructor(name) {
        this.name = name;
    }
}
// 私有函數
function privateFunction () {
    console.log('我是私有函數,外部接見不了我');
}

注意

1. 被導出的函數或許類,都必須要有稱號,意義就是說不能用這類體式格局導出匿名函數或許匿名類。
2. privateFunction 函數,沒有加 export 敕令,被當作這個模塊的私有變量,其他模塊是接見不到的。

除了上面那種導出體式格局,另有別的一種

// export2.js

// 導出變量
let name = '桃翁';

// 導出函數
function print() {
    return '迎接關注民眾號:前端桃園';
}

// 導出類
class Person {
    constructor(name) {
        this.name = name;
    }
}

// 私有函數
function privateFunction () {
    return '我是私有函數,外部接見不了我';
}

export { name, print, Person }

上面這類寫法導入一組變量,與 export1.js 是等價的。

導入模塊

導入的模塊能夠邃曉為是生產者(或許效勞的提供者),而運用導入的模塊的模塊就是消費者。

導入模塊的敕令是 import, import 的基礎情勢以下:

import { var1, var2 } from './example.js'

import 語句包括兩部份:一是導入須要的標識符,二是模塊的泉源。

注意:瀏覽器中模塊泉源要以「/」或許 「./」 或許 「../」開首 或許 url 情勢,不然會報錯。

比方我們導入 export1.js 模塊,能夠這麼導入

// import1.js
import { name, print, Person } from './export1.js';

console.log(name); // 桃翁

console.log(print()); // 迎接關注民眾號:前端桃園

// 報錯, 不能定義雷同名字變量
let name = 2333; 

// 報錯,不能從新賦值
name = "小豬";

能夠看到導入綁定(這裏不邃曉綁定,文章背面會詮釋)時,情勢類似於對象解構,但實際上並沒有關聯。

當導入綁定的時刻,綁定類似於運用了 const 定義,意味着不能定義雷同的變量名,然則沒有暫時性死區特徵(然則在 深切邃曉ES6 這本書內里說是有暫時性死區限定,我在 chrome 上測試了的,讀者願望也去試下,究竟受不受限定)。

let name = 2333;

上面這行代碼會報錯。

定名空間導入

這類導入體式格局是把全部生產者模塊當作單一對象導入,一切的導出被當作對象的屬性。

// import2.js
import * as namespace from './export1.js'

console.log(namespace.name); // 桃翁

console.log(namespace.print()); // 迎接關注民眾號:前端桃園

重定名導入導出

有時刻你並不想導出變量的原稱號,須要從新定名,這個時刻只須要運用 as 關鍵字來制訂新的名字即可。

重定名導出

// export3.js

function print() {
    return '迎接關注民眾號:前端桃園';
}

export { print as advertising }

導重定名入

拿上面導出的舉例子

// import3.js
import { advertising as print } from './export3.js'

console.log(typeof advertising); // "undefined"

console.log(print()); // 迎接關注民眾號:前端桃園 

此代碼導入 advertising 函數並重定名為了 print ,這意味着此模塊中 advertising 標識符不存在了。

default 關鍵字

default 關鍵字是用來做默許導入導出的。

默許導出

// defaultExport.js

// 第一種默許導出體式格局
export default function print() {
    return '迎接關注民眾號:前端桃園';
}

// 第二種默許導出體式格局
function print() {
    return '迎接關注民眾號:前端桃園';
}

export default print;

// 第三種默許導出體式格局
function print() {
    return '迎接關注民眾號:前端桃園';
}

export { print as default }

default 這個關鍵字在 JS 中具有特別寄義,既能夠作為同定名導出,又標清楚明了模塊須要運用默許值。

注意: 一個模塊中只能有一個默許導出。

默許導入

默許導入和平常的導入差別之處就是不須要寫大括號了,看起來更簡約。

把上面 defaultExport.js 模塊導出的作為例子

import print from './defaultExport.js'

console.log(print()); // 迎接關注民眾號:前端桃園 

那假如既有默許的又有非默許的怎樣導入呢?看例子就邃曉了

// defaultImport1.js

let name = '桃翁';

function print() {
    return '迎接關注民眾號:前端桃園';
}

export { name, print as default }
// defaultImport2.js

import print, { name } from './defaultImport1.js'

console.log(print()); // 迎接關注民眾號:前端桃園

console.log(name); // 桃翁

夾雜導入須要把默許導入的稱號放在最前面,然後用逗號和背面非默許導出的分割開。

思索了良久是不是應當加上進階內容,本來是想寫入門級系列的,然則想了想,照樣都寫進來吧,入門的看入門前面基礎,深切邃曉的看進階。

進階

進階部份重要引見 模塊的幾個特徵

  • 靜態實行
  • 動態關聯
  • 模塊不會反覆實行

靜態實行

所謂靜態實行實在就是在編譯階段就須要肯定模塊的依靠關聯,那末就會湧現 import 敕令會優先於模塊其他內容的實行,會提前到編譯階段實行。

// static1.js
console.log('佩奇');

import { nouse } from './static2.js'

// static2.js
export function nouse() {
    return '我是不須要的';
}

console.log('小豬');

能夠看到末了輸出的應當是「小豬」先輸出,而「佩奇」后輸出,能夠得出雖然 static2.js 在背面引入,然則會被提升到模塊的最前面先實行。

這也是我前面所說的不受暫時性死區緣由之一,在這裡能夠寫一個例子嘗嘗:

// static3.js
console.log(nouse());

import { nouse } from './static2.js'

// 效果:
// 小豬
// 我是不須要的

經磨練確實是能夠在 import 之前運用導入的綁定。

靜態實行還會致使一個題目,那就是不能動態導入模塊。

// 報錯
if (flag) {
    import { nouse } from './static3.js'
}

// 報錯
import { 'no' + 'use' } from './static3.js'

由於 import 是靜態實行的,所以在靜態(詞法)分析階段,是沒法獲得表達式或許變量的值的。

然則為了處理這個題目,由於了 import() 這個函數,這個算擴大內容吧,寫太多了我怕沒人看完了,背面會有擴大瀏覽鏈接。

動態關聯

所謂的動態關聯,實在就是一種綁定關聯, 這是 ES6 非常重要的特徵,肯定仔細瀏覽。

在 ES6 的模塊中,輸出的不是對象的拷貝,不管是援用範例照樣基礎範例, 都是動態關聯模塊中的值,。

// dynamic1.js
export let name = '桃翁';

export function setName(name) {
    name = name;
}

// dynamic2.js
import { name, setName } from './dynamic1.js'

console.log(name); // 桃翁

setName('不要臉');

console.log(name); // 不要臉

奇觀般的發如今 dynamic2.js 模塊中能夠修正 dynamic1.js 模塊內里的值, 而且迴響反映到 name 綁定上(這個是重點,這個迴響反映到了消費者模塊), 所以我們把導入的變量叫做綁定。

在生產者模塊導出的變量與消費者模塊導入的變量會有一個綁定關聯,不管前者或許後者發作轉變,都邑相互影響。

注意區分在一個文件或模塊中基礎範例的賦值,二者是互不影響的。

模塊不會反覆實行

這個特徵比較好邃曉,就是假如從一個生產者模塊中離別導入綁定,而不是一次性導入,生產者模塊不會實行屢次。

// noRepeat1.js
export let name = '桃翁';

export let age = '22';

console.log('我正在實行。。。');

// noRepeat2.js
import { name } from './noRepeat1.js';
import { age } from './noRepeat1.js';

console.log(name);
console.log(age);

// 效果
// 我正在實行。。。
// 桃翁
// 22

雖然導入了兩次,然則 noRepeat1.js 只要實行一次。若同一個運用(注意是同一個運用不是模塊)中導入同一個模塊,則那些模塊都邑運用一個模塊實例,意義就是說是一個單例。

跋文

碼字不容易,寫技術文章是真的累,作者花的時候至少是讀者讀的時候的十倍。在此想到阮先生寫了那末多文章,不知道是花了若干時候,居然另有人這麼恨他,進擊他的網站。

我在文章中給我民眾號打了許多廣告,在此抱個歉,剛運營的民眾號,須要拉點粉絲,不喜歡的注意內容就好。

拓展

原生ECMAScript模塊: 動態 import()

    原文作者:leexiaoran
    原文地址: https://segmentfault.com/a/1190000014859936
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞