目錄
1.模組
1.1 什麼是模組?什麼是模組化?
1.2 模組化的血淚史
局部變數
透過window連接各個模組
依賴載入的順序
#2. ES6的模組
2.1 ES6之前模組化的痛點
2.2 import和export的用法
export语法
import用法
使用import和export改写第一节的代码
2.3 拓展:import和export的一些运行原理
2.3.1 ES6 模块输出的是值的引用,输出接口会动态绑定
2.3.2 export可以出现在模块内的任何位置,但不能处于块级作用域内
2.3.3 import具有提升效果(类似于var),会提升到整个模块的头部,首先执行
首頁 web前端 js教程 什麼是模組?深刻理解ES6模組

什麼是模組?深刻理解ES6模組

Aug 09, 2018 pm 04:13 PM
es6 javascript 模組化

1.模組

1.1 什麼是模組?什麼是模組化?

玩過FPS遊戲的朋友應該知道,一把組裝完整的M4步槍,一般是槍身 消音器 倍鏡 握把 槍托

如果把M4​​步槍看成是一個頁面的話,那麼我們可以做如下類比
槍身-> <main></main>
#消音器-> <header></header>
倍鏡-> <nav></nav>
#握把-> <aside></aside>
槍托-> <footer></footer>

#OK,你剛剛做了一件事情,就是把m4步槍拆成了五個部分,你拆分的每一個部分就是一個模組【module】,你拆分的這個過程就是模組化【modularization】

模組化是一種程式設計思想,其核心就是分割任務,把複雜問題簡單化,這樣一來既方便多人分工協作,又可以幫助我們快速定位問題

  • 方便多人分工協作- 可以不同的人開發不同的模組,再組合,大大增加團隊效率

  • 幫助我們快速定位問題- 後座力太大,那八成是槍託或握把的問題;聲音過大,那八成是消音器的問題。

1.2 模組化的血淚史

下面用一個小栗子講一講模組化的發展史

龔先生和棚先生一起接了一個項目,他們兩個需要分別實現一些功能,很簡單,就是Console出來自己的變數a

於是他們倆一合計,安排龔先生的程式碼單獨放在 script1.js裡寫,棚先生的程式碼單獨放在script2.js裡寫,然後用script標籤分別引入

// script1.js文件

var a = 1
console.log(a)
登入後複製
// script2.js文件

var a = 2
console.log(a)
登入後複製
登入後複製
<!--HTML文件-->

<script src="./script1.js"></script>
<script src="./script2.js"></script>
登入後複製

很快他們遇到了第一個問題—— 變數命名衝突
尤其是包含了異步的時候,會出現如下情況

// script1.js文件

var a = 1
setTimeout(()=>{
  console.log(a)  // 我们想console出来1,却console出了2
},1000)
登入後複製
// script2.js文件

var a = 2
console.log(a)
登入後複製
登入後複製

上面的問題明顯是由於a是一個全域變數導致的,所以解決想法也很明確-造一個局部變數唄

局部變數

ES5時代使用立即執行函數製造局部變數
// script1.js文件
!function(){
    var a = 1
    setTimeout(()=>{
      console.log(a)  // 这下是2了
    },1000)
}()
// 下面有5000行代码
登入後複製
// script2.js文件

console.log(2)
登入後複製
ES6時代直接使用區塊層級作用域let
#
// script1.js文件
{
    let a = 1
    setTimeout(()=>{
      console.log(a)  // 这下是2了
    },1000)
}
登入後複製
// script2.js文件
{
    let a = 2
    console.log(a)
}
登入後複製

透過window連接各個模組

後來公司招募了一個前端大佬,說現在只能由他來控制什麼時候console變量,於是他新建了一個control.js檔案
透過window物件連接script1.js和scirpt2.js

#
// script1.js文件
{
    let a = 1
    window.module1 = function() {
        console.log(a)
    }
}
登入後複製
// script2.js文件
{
    let a = 2
    window.module2 = function() {
        console.log(a)
    }
}
登入後複製
// control.js文件
setTimeout(()=>{
    window.module1()
},1000)

window.module2()
登入後複製
登入後複製
這個時候,非常重要的一點就是window是一個全域變數並且充當了一個公用倉庫,這個倉庫有兩個關鍵作用,存【導出】取【依賴】
// script1.js文件
{
    let a = 1
    // 把这个函数存放进window,就是导出到window
    window.module1 = function() {
        console.log(a)
    }
}
登入後複製
// control.js文件
setTimeout(()=>{
    // 我们从window里取出module1函数进行调用,就是依赖了script1.js文件
    window.module1()
},1000)

window.module2()
登入後複製

依賴載入的順序

煩人的產品對需求又進行了更改,給了一個name.js文件

// name.js文件
window.names = [&#39;gongxiansheng&#39;,&#39;pengxiansheng&#39;]
登入後複製

要求現在龔先生和棚先生需要Console出自己的名字
這還不簡單?幾秒鐘寫好

// script1.js文件
{
    window.module1 = function() {
        console.log(window.names[0])
    }
}
登入後複製
// script2.js文件
{
    window.module2 = function() {
        console.log(window.names[1])
    }
}
登入後複製
// control.js文件
setTimeout(()=>{
    window.module1()
},1000)

window.module2()
登入後複製
登入後複製
<!--HTML文件-->

<script src="./script1.js"></script>
<script src="./script2.js"></script>

登入後複製

但很快他們發現,console出來的都是undefined
前端大佬一眼看出了問題,對他們倆說
你們所依賴的程式碼一定要在你們自己的程式碼前引入,不然是取不到值的;你看我的control.js是不是在你們兩個的程式碼後面引入的,因為我用到了你們兩個的程式碼了呀
噢噢,原來是js檔案載入順序問題,改一下吧

<!--HTML文件-->

<script src="./name.js"></script>
<script src="./script1.js"></script>
<script src="./script2.js"></script>
<script src="./control.js"></script>
登入後複製

但是在人多了以後,我們到時候會搞不清楚到底誰依賴了誰,保險起見只能全部都加載,性能浪費了太多,前端大佬搖頭嘆息道

#2. ES6的模組

2.1 ES6之前模組化的痛點

  1. 變數衝突

  2. 要用window連接各個模組

  3. 依賴需要全部載入

  4. 還要TMD注意載入順序

模組化是ES6的最大的亮點之一,因為在ES6之前的語法裡從未有過模組化的體系這對開發大型的、複雜的專案形成了巨大障礙。因為我們無法對專案進行拆分,無法更好地進行多人協作開發。更重要的是,其它大部分語言都支援模組化

既然語言不支持,那麼如何將模組化引入JS呢?

前端社群就自己制定了一些模組載入方案-這也是CommonJS【伺服器】和AMD、CMD【瀏覽器】的由來。
什麼是模組?深刻理解ES6模組

#
但是现在ES6引入了模块化的功能,实现起来非常简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。

2.2 import和export的用法

import和export语法较为简单,大家去MDN可以看非常详细的讲解,笔者在这里知识用注释简单介绍一下

export语法

// 命名导出
export { name1, name2, …, nameN };
export { variable1 as name1, variable2 as name2, …, nameN };
export let name1, name2, …, nameN; // also var
export let name1 = …, name2 = …, …, nameN; // also var, const
export function FunctionName() {...}
export class ClassName {...}

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

// 将其它模块内的导出作为当前文件的导出
export * from …;
export { name1, name2, …, nameN } from …;
export { import1 as name1, import2 as name2, …, nameN } from …;
登入後複製

import用法

import defaultExport from "module-name"; // 导入默认默认变量
import * as name from "module-name"; // 将模块内所有变量导出,并挂载到name下【name是一个module对象】。什么要有as——为了防止export出来的变量命名冲突
import { export } from "module-name"; // 导入某一个变量
import { export as alias } from "module-name"; // 导入某一个变量并重命名
import { export1 , export2 } from "module-name"; // 导入两个变量
import { export1 , export2 as alias2 , [...] } from "module-name"; // 导入多个变量,同时可以给导入的变量重命名
import defaultExport, { export [ , [...] ] } from "module-name"; // 导入默认变量和多个其它变量
import defaultExport, * as name from "module-name"; // 导入默认变量并重新命名
import "module-name"; // 导入并加载该文件【注意文件内的变量必须要通过export才能被使用】
var promise = import(module-name); // 异步的导入
登入後複製

使用import和export改写第一节的代码

// name.js文件
let names = [&#39;gongxiansheng&#39;,&#39;pengxiansheng&#39;]
export default names
登入後複製
// script1.js
import names from &#39;./name.js&#39;

let module1 = function () {
  console.log(names[0])
}
export default module1
登入後複製
// script2.js
import names from &#39;./name.js&#39;

let module2 = function() {
  console.log(names[1])
}
export default module2
登入後複製
// control.js
import module1 from &#39;./script1.js&#39;
import module2 from &#39;./script2.js&#39;

setTimeout(() => {
  module1()
}, 1000)
module2()
登入後複製
<!--HTML文件-->

<script type="module" src="./control.js"></script>
<!--注意一定要加上type="module",这样才会将这个script内的代码当做模块来对待-->
登入後複製

2.3 拓展:import和export的一些运行原理

2.3.1 ES6 模块输出的是值的引用,输出接口会动态绑定

其实就是按照数据类型里的引用类型的概念去理解。
这一点与 CommonJS 规范完全不同。
CommonJS 模块输出的是值的缓存,不存在动态更新。
// module1.js
export var foo = &#39;bar&#39;;
setTimeout(() => foo = &#39;baz&#39;, 500);
登入後複製
// module2.js
import {foo} from &#39;./module1.js&#39;
console.log(foo)
setTimeout(() => console.log(foo), 1000);

// console的结果
// bar
// baz
登入後複製

2.3.2 export可以出现在模块内的任何位置,但不能处于块级作用域内

// 报错
{
  export let foo = &#39;bar&#39;;
}
登入後複製

2.3.3 import具有提升效果(类似于var),会提升到整个模块的头部,首先执行

console.log(foo)
import {foo} from &#39;./script1.js&#39;
登入後複製
参考资料:ECMAScript 6 入门
本文纯属原创,为了方便大家理解,小故事,小栗子都是笔者自己想的。如果您觉得对你有帮助,麻烦给个赞,给作者灰暗的生活挥洒挥洒积极向上的正能量,谢谢啦^_^。

相关推荐:

彻底搞懂JS无缝滚动代码

彻底弄懂CSS盒子模式(DIV布局)

以上是什麼是模組?深刻理解ES6模組的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1653
14
CakePHP 教程
1413
52
Laravel 教程
1304
25
PHP教程
1251
29
C# 教程
1224
24
如何使用WebSocket和JavaScript實現線上語音辨識系統 如何使用WebSocket和JavaScript實現線上語音辨識系統 Dec 17, 2023 pm 02:54 PM

如何使用WebSocket和JavaScript實現線上語音辨識系統引言:隨著科技的不斷發展,語音辨識技術已成為了人工智慧領域的重要組成部分。而基於WebSocket和JavaScript實現的線上語音辨識系統,具備了低延遲、即時性和跨平台的特點,成為了廣泛應用的解決方案。本文將介紹如何使用WebSocket和JavaScript來實現線上語音辨識系

WebSocket與JavaScript:實現即時監控系統的關鍵技術 WebSocket與JavaScript:實現即時監控系統的關鍵技術 Dec 17, 2023 pm 05:30 PM

WebSocket與JavaScript:實現即時監控系統的關鍵技術引言:隨著互聯網技術的快速發展,即時監控系統在各個領域中得到了廣泛的應用。而實現即時監控的關鍵技術之一就是WebSocket與JavaScript的結合使用。本文將介紹WebSocket與JavaScript在即時監控系統中的應用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

如何利用JavaScript和WebSocket實現即時線上點餐系統 如何利用JavaScript和WebSocket實現即時線上點餐系統 Dec 17, 2023 pm 12:09 PM

如何利用JavaScript和WebSocket實現即時線上點餐系統介紹:隨著網路的普及和技術的進步,越來越多的餐廳開始提供線上點餐服務。為了實現即時線上點餐系統,我們可以利用JavaScript和WebSocket技術。 WebSocket是一種基於TCP協定的全雙工通訊協議,可實現客戶端與伺服器的即時雙向通訊。在即時線上點餐系統中,當使用者選擇菜餚並下訂單

如何使用WebSocket和JavaScript實現線上預約系統 如何使用WebSocket和JavaScript實現線上預約系統 Dec 17, 2023 am 09:39 AM

如何使用WebSocket和JavaScript實現線上預約系統在當今數位化的時代,越來越多的業務和服務都需要提供線上預約功能。而實現一個高效、即時的線上預約系統是至關重要的。本文將介紹如何使用WebSocket和JavaScript來實作一個線上預約系統,並提供具體的程式碼範例。一、什麼是WebSocketWebSocket是一種在單一TCP連線上進行全雙工

JavaScript與WebSocket:打造高效率的即時天氣預報系統 JavaScript與WebSocket:打造高效率的即時天氣預報系統 Dec 17, 2023 pm 05:13 PM

JavaScript和WebSocket:打造高效的即時天氣預報系統引言:如今,天氣預報的準確性對於日常生活以及決策制定具有重要意義。隨著技術的發展,我們可以透過即時獲取天氣數據來提供更準確可靠的天氣預報。在本文中,我們將學習如何使用JavaScript和WebSocket技術,來建立一個高效的即時天氣預報系統。本文將透過具體的程式碼範例來展示實現的過程。 We

簡易JavaScript教學:取得HTTP狀態碼的方法 簡易JavaScript教學:取得HTTP狀態碼的方法 Jan 05, 2024 pm 06:08 PM

JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

javascript如何使用insertBefore javascript如何使用insertBefore Nov 24, 2023 am 11:56 AM

用法:在JavaScript中,insertBefore()方法用於在DOM樹中插入一個新的節點。這個方法需要兩個參數:要插入的新節點和參考節點(即新節點將要插入的位置的節點)。

如何在JavaScript中取得HTTP狀態碼的簡單方法 如何在JavaScript中取得HTTP狀態碼的簡單方法 Jan 05, 2024 pm 01:37 PM

JavaScript中的HTTP狀態碼取得方法簡介:在進行前端開發中,我們常常需要處理與後端介面的交互,而HTTP狀態碼就是其中非常重要的一部分。了解並取得HTTP狀態碼有助於我們更好地處理介面傳回的資料。本文將介紹使用JavaScript取得HTTP狀態碼的方法,並提供具體程式碼範例。一、什麼是HTTP狀態碼HTTP狀態碼是指當瀏覽器向伺服器發起請求時,服務

See all articles