日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
JavaScript引入模塊的歷史簡介

 隨著我們的應(yīng)用越來越大,我們想要將其拆分成多個文件,即所謂的“模塊(module)”。一個模塊可以包含用于特定目的的類或函數(shù)庫。

很長一段時間,JavaScript 都沒有語言級(language-level)的模塊語法。這不是一個問題,因為最初的腳本又小又簡單,所以沒必要將其模塊化。

但是最終腳本變得越來越復(fù)雜,因此社區(qū)發(fā)明了許多種方法來將代碼組織到模塊中,使用特殊的庫按需加載模塊。

列舉一些(出于歷史原因):

  • AMD —— 最古老的模塊系統(tǒng)之一,最初由 require.js 庫實現(xiàn)。
  • CommonJS —— 為 Node.js 服務(wù)器創(chuàng)建的模塊系統(tǒng)。
  • UMD —— 另外一個模塊系統(tǒng),建議作為通用的模塊系統(tǒng),它與 AMD 和 CommonJS 都兼容。

現(xiàn)在,它們都在慢慢成為歷史的一部分,但我們?nèi)匀豢梢栽谂f腳本中找到它們。

語言級的模塊系統(tǒng)在 2015 年的時候出現(xiàn)在了標(biāo)準(zhǔn)(ES6)中,此后逐漸發(fā)展,現(xiàn)在已經(jīng)得到了所有主流瀏覽器和 Node.js 的支持。因此,我們將從現(xiàn)在開始學(xué)習(xí)現(xiàn)代 JavaScript 模塊(module)。

一、什么是模塊?

一個模塊(module)就是一個文件。一個腳本就是一個模塊。就這么簡單。

模塊可以相互加載,并可以使用特殊的指令 export 和 import 來交換功能,從另一個模塊調(diào)用一個模塊的函數(shù):

export 關(guān)鍵字標(biāo)記了可以從當(dāng)前模塊外部訪問的變量和函數(shù)。

import 關(guān)鍵字允許從其他模塊導(dǎo)入功能。

例如,我們有一個 sayHi.js 文件導(dǎo)出了一個函數(shù):

 
 
 
  1. //  sayHi.js
  2. export function sayHi(user) {
  3.   alert(`Hello, ${user}!`);
  4. }

 ……然后另一個文件可能導(dǎo)入并使用了這個函數(shù):

 
 
 
  1. //  main.js
  2. import {sayHi} from './sayHi.js';
  3. alert(sayHi); // function...
  4. sayHi('John'); // Hello, John!

 import 指令通過相對于當(dāng)前文件的路徑 ./sayHi.js 加載模塊,并將導(dǎo)入的函數(shù) sayHi 分配(assign)給相應(yīng)的變量。

讓我們在瀏覽器中運行一下這個示例。

由于模塊支持特殊的關(guān)鍵字和功能,因此我們必須通過使用

瀏覽器會自動獲取并解析(evaluate)導(dǎo)入的模塊(如果需要,還可以分析該模塊的導(dǎo)入),然后運行該腳本。

模塊只通過 HTTP(s) 工作,在本地文件則不行

如果你嘗試通過 file:// 協(xié)議在本地打開一個網(wǎng)頁,你會發(fā)現(xiàn) import/export 指令不起作用。你可以使用本地 Web 服務(wù)器,例如 static-server,或者使用編輯器的“實時服務(wù)器”功能,例如 VS Code 的 Live Server Extension 來測試模塊。

二、模塊核心功能

與“常規(guī)”腳本相比,模塊有什么不同呢?

下面是一些核心的功能,對瀏覽器和服務(wù)端的 JavaScript 來說都有效。

三、始終使用 “use strict”

模塊始終默認(rèn)使用 use strict,例如,對一個未聲明的變量賦值將產(chǎn)生錯誤(譯注:在瀏覽器控制臺可以看到 error 信息)。

 
 
 

 四、模塊級作用域

每個模塊都有自己的頂級作用域(top-level scope)。換句話說,一個模塊中的頂級作用域變量和函數(shù)在其他腳本中是不可見的。

在下面這個例子中,我們導(dǎo)入了兩個腳本,hello.js 嘗試使用在 user.js 中聲明的變量 user,失敗了:

 
 
 

 模塊期望 export 它們想要被外部訪問的內(nèi)容,并 import 它們所需要的內(nèi)容。

所以,我們應(yīng)該將 user.js 導(dǎo)入到 hello.js 中,并從中獲取所需的功能,而不要依賴于全局變量。

這是正確的變體:

 
 
 
  1. import {user} from './user.js';
  2. document.body.innerHTML = user; // John

 在瀏覽器中,每個

  •  如果我們真的需要創(chuàng)建一個 window-level 的全局變量,我們可以將其明確地賦值給 window,并以 window.user 來訪問它。但是這需要你有足夠充分的理由,否則就不要這樣做。

    五、模塊代碼僅在第一次導(dǎo)入時被解析

    如果同一個模塊被導(dǎo)入到多個其他位置,那么它的代碼僅會在第一次導(dǎo)入時執(zhí)行,然后將導(dǎo)出(export)的內(nèi)容提供給所有的導(dǎo)入(importer)。

    這有很重要的影響。讓我們通過示例來看一下:

    首先,如果執(zhí)行一個模塊中的代碼會帶來副作用(side-effect),例如顯示一條消息,那么多次導(dǎo)入它只會觸發(fā)一次顯示 —— 即第一次:

     
     
     
    1. //  alert.js
    2. alert("Module is evaluated!");

     
     
     
    1. // 在不同的文件中導(dǎo)入相同的模塊
    2. //  1.js
    3. import `./alert.js`; // Module is evaluated!
    4. //  2.js
    5. import `./alert.js`; // (什么都不顯示)

     在實際開發(fā)中,頂級模塊代碼主要用于初始化,內(nèi)部數(shù)據(jù)結(jié)構(gòu)的創(chuàng)建,并且如果我們希望某些東西可以重用 — 請導(dǎo)出它。

    下面是一個高級點的例子。

    我們假設(shè)一個模塊導(dǎo)出了一個對象:

     
     
     
    1. //  admin.js
    2. export let admin = {
    3.   name: "John"
    4. };

     如果這個模塊被導(dǎo)入到多個文件中,模塊僅在第一次被導(dǎo)入時被解析,并創(chuàng)建 admin 對象,然后將其傳入到所有的導(dǎo)入。

    所有的導(dǎo)入都只獲得了一個唯一的 admin 對象:

     
     
     
    1. //  1.js
    2. import {admin} from './admin.js';
    3. admin.name = "Pete";
    4. //  2.js
    5. import {admin} from './admin.js';
    6. alert(admin.name); // Pete
    7. // 1.js 和 2.js 導(dǎo)入的是同一個對象
    8. // 在 1.js 中對對象做的更改,在 2.js 中也是可見的

     所以,讓我們重申一下 —— 模塊只被執(zhí)行一次。生成導(dǎo)出,然后它被分享給所有對其的導(dǎo)入,所以如果某個地方修改了 admin 對象,其他的模塊也能看到這個修改。

    這種行為讓我們可以在首次導(dǎo)入時 設(shè)置 模塊。我們只需要設(shè)置其屬性一次,然后在進(jìn)一步的導(dǎo)入中就都可以直接使用了。

    例如,下面的 admin.js 模塊可能提供了特定的功能,但是希望憑證(credential)從外部進(jìn)入 admin 對象:

     
     
     
    1. //  admin.js
    2. export let admin = { };
    3. export function sayHi() {
    4.   alert(`Ready to serve, ${admin.name}!`);
    5. }

     在 init.js 中 —— 我們 APP 的第一個腳本,設(shè)置了 admin.name。現(xiàn)在每個位置都能看到它,包括在 admin.js 內(nèi)部的調(diào)用。

     
     
     
    1. //  init.js
    2. import {admin} from './admin.js';
    3. admin.name = "Pete";

     另一個模塊也可以看到 admin.name:

     
     
     
    1. //  other.js
    2. import {admin, sayHi} from './admin.js';
    3. alert(admin.name); // Pete
    4. sayHi(); // Ready to serve, Pete!

     六、import.meta

    import.meta 對象包含關(guān)于當(dāng)前模塊的信息。

    它的內(nèi)容取決于其所在的環(huán)境。在瀏覽器環(huán)境中,它包含當(dāng)前腳本的 URL,或者如果它是在 HTML 中的話,則包含當(dāng)前頁面的 URL。

     
     
     

     七、在一個模塊中,“this” 是 undefined

    這是一個小功能,但為了完整性,我們應(yīng)該提到它。

    在一個模塊中,頂級 this 是 undefined。

    將其與非模塊腳本進(jìn)行比較會發(fā)現(xiàn),非模塊腳本的頂級 this 是全局對象:

     
     
     

     八、瀏覽器特定功能

    與常規(guī)腳本相比,擁有 type="module" 標(biāo)識的腳本有一些特定于瀏覽器的差異。

    如果你是第一次閱讀或者你不打算在瀏覽器中使用 JavaScript,那么你可以跳過本節(jié)內(nèi)容。

    九、模塊腳本是延遲的

    模塊腳本 總是 被延遲的,與 defer 特性(在 腳本:async,defer 一章中描述的)對外部腳本和內(nèi)聯(lián)腳本(inline script)的影響相同。

    也就是說: