在互聯網的洪荒時代,網站主要用 HTML和 CSS 開發的。如果將 JavaScript 加載到頁面中,通常是以小片段的形式提供效果和交互,一般會把所有的 JavaScript 代碼全都寫在一個文件中,并加載到一個 script
標簽中。盡管可以把 JavaScript 拆分為多個文件,但是所有的變量和函數仍然會被添加到全局作用域中。
但是后來 JavaScript 在瀏覽器中發揮著重要的作用,迫切需要使用第三方代碼來完成常見任務,并且需要把代碼分解為模塊化的文件,避免污染全局命名空間。
ECMAScript 2015 規范在 JavaScript 語言中引入了 module,也有了 import 和 export 語句。在本文中,我們一起來學習 JavaScript 模塊,以及怎樣用 import
和 export
來組織代碼。
在 JavaScript 中出現模塊的概念之前,當我們想要把自己的代碼組織為多個塊時,一般會創建多個文件,并且將它們鏈接為單獨的腳本。下面先舉例說明,首先創建一個 index.html
文件和兩個JavaScript文件“ functions.js
和 script.js
。
index.html
文件用來顯示兩個數字的和、差、乘積和商,并鏈接到 script
標簽中的兩個 JavaScript 文件。打開 index.html
并添加以下代碼:
index.html
<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>JavaScript Modules</title> </head> <body> <h2>Answers</h2> <h3><strong id="x"></strong> and <strong id="y"></strong></h3> <h4>Addition</h4> <p id="addition"></p> <h4>Subtraction</h4> <p id="subtraction"></p> <h4>Multiplication</h4> <p id="multiplication"></p> <h4>pision</h4> <p id="pision"></p> <script src="functions.js"></script> <script src="script.js"></script> </body></html>
這個頁面很簡單,就不詳細說明了。
functions.js
文件中包含將會在第二個腳本中用到的數學函數。打開文件并添加以下內容:
functions.js
function sum(x, y) { return x + y}function difference(x, y) { return x - y}function product(x, y) { return x * y}function quotient(x, y) { return x / y}
最后,script.js
文件用來確定 x 和 y 的值,以及調用前面那些函數并顯示結果:
script.js
const x = 10const y = 5document.getElementById('x').textContent = xdocument.getElementById('y').textContent = ydocument.getElementById('addition').textContent = sum(x, y)document.getElementById('subtraction').textContent = difference(x, y)document.getElementById('multiplication').textContent = product(x, y)document.getElementById('pision').textContent = quotient(x, y)
保存之后在瀏覽器中打開 index.html
可以看到所有結果:
對于只需要一些小腳本的網站,這不失為一種有效的組織代碼的方法。但是這種方法存在一些問題:
sum
、 difference
等)現在都存在于 window
對象中。如果你打算在另一個文件中使用另一個名為 sum
的變量,會很難知道在腳本的其它位置到底用的是哪一個值變量,因為它們用的都是相同的 window.sum
變量。唯一可以使變量私有的方法是將其放在函數的作用域中。甚至在 DOM 中名為 x
的 id
可能會和 var x
存在沖突。 <script>
中相同。在 ES6 把原生模塊添加到 JavaScript 語言之前,社區曾經嘗試著提供了幾種解決方案。第一個解決方案是用原生 JavaScript 編寫的,例如將所有代碼都寫在 objects 或立即調用的函數表達式(IIFE)中,并將它們放在全局命名空間中的單個對象上。這是對多腳本方法的一種改進,但是仍然存在將至少一個對象放入全局命名空間的問題,并沒有使在第三方之間一致地共享代碼的問題變得更加容易。
之后又出現了一些模塊解決方案:CommonJS 是一種在 Node.js 實現的同步方法,異步模塊定義(AMD)是一種異步方法,還有支持前面兩種樣式的通用方法——通用模塊定義(UMD)。
這些解決方案的出現使我們可以更輕松地以包的形式共享和重用代碼,也就是可以分發和共享的模塊,例如 npm。但是由于存在許多解決方案,并且都不是 JavaScript 原生的,所以需要依靠 Babel、Webpack 或 Browserify之類的工具才能在瀏覽器中使用。
由于多文件方法存在許多問題,并且解決方案很復雜,所以開發人員對把模塊化開發的方法引入 JavaScript 語言非常感興趣。于是 ECMAScript 2015 開始支持 JavaScript module。
module 是一組代碼,用來提供其他模塊所使用的功能,并能使用其他模塊的功能。 export 模塊提供代碼,import 模塊使用其他代碼。模塊之所以有用,是因為它們允許我們重用代碼,它們提供了許多可用的穩定、一致的接口,并且不會污染全局命名空間。
模塊(有時稱為 ES 模塊)現在可以在原生 JavaScript 中使用,在本文中,我們一起來探索怎樣在代碼中使用及實現。
JavaScript 中的模塊使用import
和 export
關鍵字:
import
:用于讀取從另一個模塊導出的代碼。export
:用于向其他模塊提供代碼。接下來把前面的的 functions.js
文件更新為模塊并導出函數。在每個函數的前面添加 export
。
functions.js
export function sum(x, y) { return x + y}export function difference(x, y) { return x - y}export function product(x, y) { return x * y}export function quotient(x, y) { return x / y}
在 script.js
中用 import
從前面的 functions.js
模塊中檢索代碼。
注意:import
必須始終位于文件的頂部,然后再寫其他代碼,并且還必須包括相對路徑(在這個例子里為./
)。
把 script.js
中的代碼改成下面的樣子:
script.js
import { sum, difference, product, quotient } from './functions.js'const x = 10const y = 5document.getElementById('x').textContent = xdocument.getElementById('y').textContent = ydocument.getElementById('addition').textContent = sum(x, y)document.getElementById('subtraction').textContent = difference(x, y)document.getElementById('multiplication').textContent = product(x, y)document.getElementById('pision').textContent = quotient(x, y)
注意:要通過在花括號中命名單個函數來導入。
為了確保代碼作為模塊導入,而不是作為常規腳本加載,要在 index.html
中的 script
標簽中添加type="module"
。任何使用 import
或 export
的代碼都必須使用這個屬性:
index.html
<script type="module" src="functions.js"></script><script type="module" src="script.js"></script>
由于受限于 CORS 策略,必須在服務器環境中使用模塊,否則會出現下面的錯誤:
Access to script at 'file:///Users/your_file_path/script.js' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, chrome-untrusted, https.
模塊與常規腳本不一樣的地方:
window
)作用域添加任何內容。模塊仍然經常與打包程序(如 Webpack)一起配合使用,用來增加對瀏覽器的支持和附加功能,但它們也可以直接用在瀏覽器中。
接下來探索更多使用 import
和 export
語法的方式。
如前所述,使用 export
語法允許你分別導入按名稱導出的值。以這個 function.js
的簡化版本為例:
functions.js
export function sum() {}export function difference() {}
這樣允許你用花括號按名稱導入 sum
和 difference
:
script.js
import {sum, difference} from './functions.js'
也可以用別名來重命名該函數。這樣可以避免在同一模塊中產生命名沖突。在這個例子中,sum
將重命名為 add
,而 difference
將重命名為 subtract
。
script.js
import { sum as add, difference as subtract} from './functions.js'add(1, 2) // 3
在這里調用 add()
將產生 sum()
函數的結果。
使用 *
語法可以將整個模塊的內容導入到一個對象中。在這種情況下,sum
和 difference
將成為 mathFunctions
對象上的方法。
script.js
import * as mathFunctions from './functions.js'mathFunctions.sum(1, 2) // 3mathFunctions.difference(10, 3) // 7
原始值、函數表達式和定義、異步函數、類和實例化的類都可以導出,只要它們有標識符就行:
// 原始值export const number = 100export const string = 'string'export const undef = undefinedexport const empty = nullexport const obj = {name: 'Homer'}export const array = ['Bart', 'Lisa', 'Maggie']// 函數表達式export const sum = (x, y) => x + y// 函數定義export function difference(x, y) { return x - y}// 匿名函數export async function getBooks() {}// 類export class Book { constructor(name, author) { this.name = name this.author = author }}// 實例化類export const book = new Book('Lord of the Rings', 'J. R. R. Tolkein')
所有這些導出都可以成功被導入。接下來要探討的另一種導出類型稱為默認導出。
在前面的例子中我們導出了多個命名的導出,并分別或作為一個對象導入了每個導出,將每個導出作為對象上的方法。模塊也可以用關鍵字 default
包含默認導出。默認導出不使用大括號導入,而是直接導入到命名標識符中。
以 functions.js
文件為例:
functions.js
export default function sum(x, y) { return x + y}
在 script.js
文件中,可以用以下命令將默認函數導入為 sum
:
script.js
import sum from './functions.js'sum(1, 2) // 3
不過這樣做很危險,因為在導入過程中對默認導出的命名沒有做任何限制。在這個例子中,默認函數被導入為 difference
,盡管它實際上是 sum
函數:
script.js
import difference from './functions.js'difference(1, 2) // 3
所以一般首選使用命名導出。與命名導出不同,默認導出不需要標識符——原始值本身或匿名函數都可以用作默認導出。以下是用作默認導出的對象的示例:
functions.js
export default { name: 'Lord of the Rings', author: 'J. R. R. Tolkein',}
可以用以下命令將其作為 book
導入:
functions.js
import book from './functions.js'
同樣,下面的例子演示了如何將匿名箭頭函數導出為默認導出:
functions.js
export default () => 'This function is anonymous'
可以這樣導入:
script.js
import anonymousFunction from './functions.js'
命名導出和默認導出可以彼此并用,例如在這個模塊中,導出兩個命名值和一個默認值:
functions.js
export const length = 10export const width = 5export default function perimeter(x, y) { return 2 * (x + y)}
可以用以下命令導入這些變量和默認函數:
script.js
import calculatePerimeter, {length, width} from './functions.js'calculatePerimeter(length, width) // 30
現在默認值和命名值都可用于腳本了。
關于javascript中的modules、import和export是什么意思就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
本文由 貴州做網站公司 整理發布,部分圖文來源于互聯網,如有侵權,請聯系我們刪除,謝謝!
c語言中正確的字符常量是用一對單引號將一個字符括起表示合法的字符常量。例如‘a’。數值包括整型、浮點型。整型可用十進制,八進制,十六進制。八進制前面要加0,后面...
2022年天津專場考試原定于3月19日舉行,受疫情影響確定延期,但目前延期后的考試時間推遲。 符合報名條件的考生,須在規定時間登錄招考資訊網(www.zha...
:喜歡聽,樂意看。指很受歡迎?!巴卣官Y料”喜聞樂見:[ xǐ wén lè jiàn ]詳細解釋1. 【解釋】:喜歡聽,樂意看。指很受歡迎。2. 【示例】:這是...
巴菲特不少人都會知道的,因為他經常榮登人物雜志封面或者是出現在財經類的刊物上,也是被股民稱為“股神”,我們很想要與巴菲特交流一下股票的知識。但是巴菲特我們一般都是無法見面的,那么巴菲特選股十招可以學習一下。排在第一位的竟然是需要做到心中無股。這個是什么意思呢?就是大家在買股票前不要只想著盈利賺錢,需要去考核該股所在公司的的前景和價值,需要選擇哪種有價值的股票公司進行投資;排...
在上一篇文章中,筆者和大家聊了四平市、長春市等吉林省城市經濟發展和區劃變化的一系列故事。今天,我們來談談吉林省吉林市。吉林市是全國唯一同名的地級市。吉林市是吉林省的舊都,也是吉林省的重要城市。目前,吉林市下轄9個區縣。那么,吉林九區縣的格局是如何一步步形成的呢?首先說一下吉林省的基本情況。首先說一下吉林省的基本情況。吉林省屬于中國東北三省之一,是中國的糧食大省。吉林省礦產資源和糧食產量豐富。根據2...
在辦公室坐八個小時,不知不覺總會出現各種小問題。腰有點酸,肩膀總有小疼,還有皮膚干燥,月經不調,等等。這些小問題是否讓你只是單純的“累”來說明問題?疲勞、壓力、坐姿甚至辦公室里的空音調都可能不斷侵犯你的健康和美麗,調整這些不良狀況并不難。學習中醫艾灸,每天只需10分鐘,就能讓你輕松告別小毛??!迎來一個精神清爽、膚色如春的全新好狀態。古老而神秘的艾灸,如今已經成為養生專家和美容專家之間的新時尚。艾灸...