1. 程式人生 > >ES6之路之模組詳解

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 只有執行一次。若同一個應用(注意是同一個應用不是模組)中匯入同一個模組,則那些模組都會使用一個模組例項,意思就是說是一個單例。

後記

碼字不易,寫技術文章是真的累,作者花的時間至少是讀者讀的時間的十倍。在此想到阮老師寫了那麼多文章,不知道是花了多少時間,竟然還有人這麼恨他,攻擊他的網站。

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

拓展

相關推薦

python目錄操作os.path模組

os.path模組 注意:匯入os模組或os.path模組都可以使用下面介紹的方法 os.path.exists(path):判斷指定目錄是否存在 >>> import os.path >>> if os.path.exists("D:\\tes

spring原始碼分析spring-jdbc模組

0 概述 Spring將替我們完成所有使用JDBC API進行開發的單調乏味的、底層細節處理工作。下表描述了哪些是spring幫助我們做好的,哪些是我們要做的。 Action  Spring  You Define connection parameters.  X

spring原始碼分析spring-messaging模組

0 概述 spring-messaging模組為整合messaging api和訊息協議提供支援。 其程式碼結構為: 其中base定義了訊息Message(MessageHeader和body)、訊息處理MessageHandler、傳送訊息MessageChann

ES6模組

簡介 何為模組 一個模組只不過是一個寫在檔案中的 JavaScript 程式碼塊。 模組中的函式或變數不可用,除非模組檔案匯出它們。 簡單地說,這些模組可以幫助你在你的模組中編寫程式碼,並且只公開應該被你的程式碼的其他部分訪問的程式碼部分。 為

網路學習基礎 計算機網路與Internet

網路學習之路之基礎詳解① 計算機網路概述之整體瞭解 首先我們理清總體思路,來看看計算機網路概述整體的框圖 從上圖我們可以大致瞭解到計算機網路包含內容,下面我們來對各方面進行詳細學習: (1)計算機網路VS Internet ①基礎理解: 計算機網路:一些互相連線的,自治的計算機的

python目錄操作os模組

os模組 os.getcwd():獲取當前目錄 >>> import os >>> os.getcwd() 'C:\\Users\\zhigang\\Desktop' os.chdir(path):切換目錄 >>> os.

Python3.5——內建模組os模組、sys模組、shutil模組

1、os模組:提供對作業系統進行呼叫的介面 #!/usr/bin/env python # -*- coding:utf-8 -*- # Author:ZhengzhengLiu import os print(os.getcwd()) #獲取當前的操作目錄,即當前

Python3Requests模組

# 匯入 Request模組 # 若本機無自帶Request模組,可自行下載或者使用pip進行安裝 # python版本Python3 import requests import json #######################Get請求######

Python3模組--老司機工具urllib模組urllib.parse子模組

This module defines a standard interface to break Uniform Resource Locator (URL) strings up in components (addressing scheme, network lo

python+selenium自動化測試Day4pycharm的使用

前言         在寫指令碼之前,先要找個順手的寫指令碼工具。python是一門解釋性程式語言,所以一般把寫python的工具叫直譯器。寫python指令碼的工具很多,小編這裡就不一一列舉的,只要自己用著順手就可以的,如果你還沒有選好直譯器,小編這裡推薦pychar

Python3模組--老司機工具urllib模組urllib.request子模組

urllib模組中常見的模組就是urllib.request模組,對於這個模組我會深入講解一下,因為Python3.3.0之後,它的用法有了一個變化,在開發的過程中需要大家注意: The urllib

Python3.5——內建模組random模組

1、random模組基礎的方法 #!/usr/bin/env python # -*- coding:utf-8 -*- # Author:ZhengzhengLiu import random

元件化開發路由器模組(ActivityRouter原始碼

    路由器的作用是什麼?通俗的講,路由器的作用就是一根網線滿足多人上網的需求。而在開發中路由器模組的作用就是實現中轉分發,也就是說將原來有關係的模組(有依賴的模組分開),產生一箇中間的模組,讓原來依賴的兩個模組都去和路由模組互動,從而將原來兩個有關係的模組拆分開,利如我現

Python美[從菜鳥到高手]--Python垃圾回收機制及gc模組

    Python中的垃圾回收是以引用計數為主,標記-清除和分代收集為輔。引用計數最大缺陷就是迴圈引用的問題,所以Python採用了輔助方法。本篇文章並不詳細探討Python的垃圾回收機制的內部實現,而是以gc模組為切入點學習Python的垃圾回收機制,如果想深入可以讀讀

Python 正則re模組compile()和findall()

首先我們看下官方文件裡關於的compile的說明: re.compile(pattern, flags=0) Compile a regular expression pattern into a regular expression object, which can

pythonimport模組

python包含子目錄中的模組方法比較簡單,關鍵是能夠在sys.path裡面找到通向模組檔案的路徑。 下面將具體介紹幾種常用情況: 1、主程式與模組程式在同一目錄下: 如下面程式結構: `-- src     |-- mod1.py     `-- test1.py    

MVCAjax.BeginForm使用更新列表

分布 use html text col 返回 uno pts scripts 1.首先,請在配置文件設置如下:(該項默認都存在且為true) <add key="UnobtrusiveJavaScriptEnabled" value="true" /> 2

Android應用開發所有動畫使用

factory 技術分享 resource bsp phi 顯示 程序 恢復 分享 題外話:有段時間沒有更新博客了,這篇文章也是之前寫了一半一直放在草稿箱,今天抽空把剩余的補上的。消失的這段時間真的好忙,節奏一下子有些適應不過來,早晨七點四十就得醒來,晚上九點四十才準備下班

mysqlgroup_concat函數

sel style 舉例 back spa -1 逗號 src asc 函數語法: group_concat([DISTINCT] 要連接的字段 [ORDER BY 排序字段 ASC/DESC] [SEPARATOR ‘分隔符‘]) 下面舉例說明: select * fro

(轉)Arcgis for JsGraphiclayer擴展

不同的 nes library 創建 都是 拖拽 oms hang graph http://blog.csdn.net/gisshixisheng/article/details/41208185 在前兩節,講到了兩種不同方式的聚類,一種是基於距離的,一種是基於區域範圍