Module載入的詳細說明-保證你有所收穫

来源:https://www.cnblogs.com/IwishIcould/archive/2022/09/26/16732805.html
-Advertisement-
Play Games

模塊 HTML 網頁中,瀏覽器通過<script>標簽載入 JavaScript 腳本。 <!-- 頁面內嵌的腳本 --> <script type="application/javascript"> // module code </script> <!-- 外部腳本 --> <script ty ...


模塊

HTML 網頁中,瀏覽器通過<script>標簽載入 JavaScript 腳本。
<!-- 頁面內嵌的腳本 -->
<script type="application/javascript">
  // module code
</script>

<!-- 外部腳本 -->
<script type="application/javascript" src="path/to/myModule.js">
</script>
上面代碼中由於瀏覽器腳本的預設語言是 JavaScript。
因此type="application/javascript"可以省略。

瀏覽器同步載入 JavaScript 腳本可能會產生的問題

預設情況下,瀏覽器是同步載入 JavaScript 腳本.
即渲染引擎遇到<script>標簽就會停下來,等JavaScript腳本執行完後,再繼續向下渲染。
如果是外部腳本,還必須加入腳本下載的時間。下載完成後,在執行。
如果腳本體積很大,下載和執行的時間就會很長,因此造成瀏覽器堵塞。
用戶會感覺到瀏覽器“卡死”了,沒有任何響應。這顯然是很不好的體驗。
然後就出現了非同步載入腳本的兩種語法

非同步載入腳本的兩種語法 defer或async

<script src="path/to/myModule.js" defer></script>
<script src="path/to/myModule.js" async></script>
上面代碼中,<script>標簽打開defer或async屬性,腳本就會非同步載入。
渲染引擎遇到這一行命令,就會開始下載外部腳本,但不會等它下載和執行,而是直接執行後面的命令。

defer 與 async的區別是

defer:要等到整個頁面在記憶體中正常渲染結束(DOM 結構完全生成,以及其他腳本執行完成),才會執行;
async:一旦下載完,渲染引擎就會中斷渲染,執行這個腳本以後,再繼續渲染。
一句話,defer是“渲染完再執行”,async是“下載完就執行”。
另外,如果有多個defer腳本,會按照它們在頁面出現的順序載入,而多個async腳本是不能保證載入順序的。

瀏覽器載入 ES6 模塊

瀏覽器載入 ES6 模塊,也使用<script>標簽,但是要加入type="module"屬性。
<script type="module" src="./foo.js"></script>
瀏覽器就知道這是一個es6模塊。
瀏覽器對於帶有type="module"的<script>,都是非同步載入,不會造成堵塞瀏覽器。
即等到整個頁面渲染完,再執行<script type="module" src="./foo.js"></script>模塊腳本
也就是說 type="module" 等價於 defer
如果網頁有多個<script type="module">,它們會按照在頁面出現的順序依次執行。

模塊引入的註意點

模塊之中,可以使用import命令載入其他模塊(.js尾碼不可省略,需要提供絕對 URL 或相對 URL)。
也可以使用export命令輸出對外介面。
同一個模塊如果載入多次,將只執行一次。

ES6 模塊與 CommonJS 模塊的差異

1.ommonJS 模塊輸出的是一個值的拷貝,輸出的是值。ES6 模塊輸出的是值的引用。
2.CommonJS 模塊是運行時載入,ES6 模塊是編譯時輸出介面。
3.CommonJS 模塊的require()是同步載入模塊。ES6 模塊的import命令是非同步載入,

詳細說下他們的第1個差異

CommonJS 模塊輸出的是值的拷貝,也就是說,一旦輸出一個值。
模塊內部的變化就影響不到這個值。請看下麵這個模塊文件
// lib.js
var counter = 3;
function incCounter() {
  counter++;
}
module.exports = {
  counter: counter,
  incCounter: incCounter,
};

上面代碼輸出內部變數counter和改寫這個變數的內部方法incCounter。然後,在main.js裡面載入這個模塊。

// main.js
var mod = require('./lib');
console.log(mod.counter);  // 3
mod.incCounter(); //調用
console.log(mod.counter); // 3
上面代碼說明,
lib.js模塊載入以後,它的內部變化就影響不到輸出的值 mod.counter 了。
這是因為mod.counter是一個原始類型的值,會被緩存。除非寫成一個函數,才能得到內部變動後的值。
// lib.js
var counter = 3;
function incCounter() {
  counter++;
}
module.exports = {
  get counter() {
    return counter
  },
  incCounter: incCounter,
};

// main.js
var mod = require('./lib');
console.log(mod.counter);  // 3
mod.incCounter(); //調用
console.log(mod.counter); // 4
ES6 模塊的運行機制與 CommonJS 不一樣。
JS 引擎對腳本靜態分析的時候,遇到模塊載入命令import,就會生成一個只讀引用。
等到腳本真正執行時,再根據這個只讀引用到被載入的那個模塊裡面去取值。
換句話說,ES6 的import有點像 Unix 系統的“符號連接”,原始值變了,import載入的值也會跟著變。
因此,ES6 模塊是動態引用,並且不會緩存值,模塊裡面的變數綁定其所在的模塊。
還是舉上面的例子。
// lib.js
export let counter = 3;
export function incCounter() {
  counter++;
}

// main.js
import { counter, incCounter } from './lib';
console.log(counter); // 3
incCounter();
console.log(counter); // 4

在舉一個小粒子

// m1.js
export var foo = 'bar';
setTimeout(() => foo = 'baz', 500);

// m2.js
import {foo} from './m1.js';
console.log(foo);
setTimeout(() => console.log(foo), 500);
上面代碼中,m1.js的變數,foo,在剛載入時等於bar,過了 500 毫秒,又變為等於baz。

Node.js 的模塊載入方法

JavaScript 現在有兩種模塊。一種是 ES6 模塊,簡稱 ESM;另一種是 CommonJS 模塊,簡稱 CJS。
CommonJS 模塊是 Node.js 專用的,與 ES6 模塊不相容。
語法上面,兩者最明顯的差異是,CommonJS 模塊使用require()和module.exports.
ES6 模塊使用import和export。

ps:從 Node.js v13.2 版本開始,Node.js 已經預設打開了 ES6 模塊支持。
Node.js 要求 ES6 模塊採用.mjs尾碼文件名。
也就是說,只要腳本文件裡面使用import或者export命令,那麼就必須採用.mjs尾碼名。
Node.js 遇到.mjs文件,就認為它是 ES6 模塊,預設啟用嚴格模式,不必在每個模塊文件頂部指定"use strict"。

友情提示

註意,ES6 模塊與 CommonJS 模塊儘量不要混用。require命令不能載入.mjs文件,會報錯。
只有import命令才可以載入.mjs文件。反過來.mjs文件裡面也不能使用require命令,必須使用import。

簡單說一下他們的第2個差異

第二個差異是因為 CommonJS 載入的是一個對象,通過 module.exports 輸出。該對象只有在腳本運行完才會生成。
而ES6 模塊不是對象,它的對外介面只是一種【靜態定義】,在代碼靜態解析階段就會生成。

遇見問題,這是你成長的機會,如果你能夠解決,這就是收穫。

作者:晚來南風晚相識
出處:https://www.cnblogs.com/IwishIcould/

想問問題,打賞了卑微的博主,求求你備註一下的扣扣或者微信;這樣我好聯繫你;(っ•̀ω•́)っ✎⁾⁾!

如果覺得這篇文章對你有小小的幫助的話,記得在右下角點個“推薦”哦,或者關註博主,在此感謝!

萬水千山總是情,打賞5毛買辣條行不行,所以如果你心情還比較高興,也是可以掃碼打賞博主(っ•̀ω•́)っ✎⁾⁾!

想問問題,打賞了卑微的博主,求求你備註一下的扣扣或者微信;這樣我好聯繫你;(っ•̀ω•́)っ✎⁾⁾!

支付寶 微信 本文版權歸作者所有,歡迎轉載,未經作者同意須保留此段聲明,在文章頁面明顯位置給出原文連接
如果文中有什麼錯誤,歡迎指出。以免更多的人被誤導。

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 摘要:面向教育模式的轉變,南京功夫豆攜手華為雲IoT,給印表機配上與雲端互通的智能盒子,開啟雲端列印新模式 本文分享自華為雲社區《一臺“厲害”的印表機:雲+IoT,開啟雲端列印新模式》,作者:華為IoT雲服務 。 後疫情時代 生活的各方面都在往線上模式延展 而在不被人註意的角落裡 印表機也在悄悄地提 ...
  • 1. 前言 什麼是Linux Linux是一套免費使用和自由傳播的操作系統。說到操作系統,大家比較熟知的應該就是Windows和MacOS操作系統,我們今天所學習的Linux也是一款操作系統。 為什麼要學Linux 那麼我們為什麼要學習Linux呢,主要出於兩個方面的原因。 1). 企業用人要求 以 ...
  • cobbler部署 #先關閉防火牆和selinux [root@localhost ~]# systemctl disable firewalld [root@localhost ~]# setenforce 0 //cobbler服務,selinux必須得是disabled狀態,所以要重啟 [ro ...
  • 前幾天裝了幾台伺服器測試,在使用的過程中發現,每次重啟系統,登錄界面會彈出網卡提示 “r8169 0000:02:00 eth0 Invalid ocp reg 17758!” 系統版本: 經過測試發現: 1、開機前將eth0/eth1網口插上網線,系統啟動後識別到eth0/eth1網口有網線連接, ...
  • 前言 什麼是Redis Redis是一個基於記憶體的key-value結構資料庫。Redis 是互聯網技術領域使用最為廣泛的存儲中間件,它是「Remote Dictionary Service」的首字母縮寫,也就是「遠程字典服務」。 [ ] 基於記憶體存儲,讀寫性能高 [ ] 適合存儲熱點數據(熱點商品 ...
  • 摘要:本文主要介紹 Presto 如何更好的利用 Hudi 的數據佈局、索引信息來加速點查性能。 本文分享自華為雲社區《華為雲基於 Apache Hudi 極致查詢優化的探索實踐!》,作者:FI_mengtao。 背景 湖倉一體(LakeHouse)是一種新的開放式架構,它結合了數據湖和數據倉庫的最 ...
  • 雲端分析是針對 CocoaPods 依賴管理雲端化的優化方案。對大量重覆的 iOS 工程構建任務進行了收斂和資源復用,在保證正確性的前提下達到了加速依賴管理速率的目的,實現了 Pod install 分析階段提速 60% 以上的能力。 ...
  • 華為帳號自擬形象上線啦!用戶只需一張照片,即可輕鬆創建屬於自己的華為帳號自擬形象,還能對形象進行個性化裝扮,DIY髮型、服裝、配飾等。點擊“手機設置 > 華為帳號 > 自擬形象 ”即刻擁有手機中的另一個你。 華為帳號自擬形象提供數個預置虛擬形象供用戶直接使用,用戶也能夠通過拍攝/上傳照片,一鍵生成照 ...
一周排行
    -Advertisement-
    Play Games
  • 概述:在C#中,++i和i++都是自增運算符,其中++i先增加值再返回,而i++先返回值再增加。應用場景根據需求選擇,首碼適合先增後用,尾碼適合先用後增。詳細示例提供清晰的代碼演示這兩者的操作時機和實際應用。 在C#中,++i 和 i++ 都是自增運算符,但它們在操作上有細微的差異,主要體現在操作的 ...
  • 上次發佈了:Taurus.MVC 性能壓力測試(ap 壓測 和 linux 下wrk 壓測):.NET Core 版本,今天計劃準備壓測一下 .NET 版本,來測試並記錄一下 Taurus.MVC 框架在 .NET 版本的性能,以便後續持續優化改進。 為了方便對比,本文章的電腦環境和測試思路,儘量和... ...
  • .NET WebAPI作為一種構建RESTful服務的強大工具,為開發者提供了便捷的方式來定義、處理HTTP請求並返迴響應。在設計API介面時,正確地接收和解析客戶端發送的數據至關重要。.NET WebAPI提供了一系列特性,如[FromRoute]、[FromQuery]和[FromBody],用 ...
  • 原因:我之所以想做這個項目,是因為在之前查找關於C#/WPF相關資料時,我發現講解圖像濾鏡的資源非常稀缺。此外,我註意到許多現有的開源庫主要基於CPU進行圖像渲染。這種方式在處理大量圖像時,會導致CPU的渲染負擔過重。因此,我將在下文中介紹如何通過GPU渲染來有效實現圖像的各種濾鏡效果。 生成的效果 ...
  • 引言 上一章我們介紹了在xUnit單元測試中用xUnit.DependencyInject來使用依賴註入,上一章我們的Sample.Repository倉儲層有一個批量註入的介面沒有做單元測試,今天用這個示例來演示一下如何用Bogus創建模擬數據 ,和 EFCore 的種子數據生成 Bogus 的優 ...
  • 一、前言 在自己的項目中,涉及到實時心率曲線的繪製,項目上的曲線繪製,一般很難找到能直接用的第三方庫,而且有些還是定製化的功能,所以還是自己繪製比較方便。很多人一聽到自己畫就害怕,感覺很難,今天就分享一個完整的實時心率數據繪製心率曲線圖的例子;之前的博客也分享給DrawingVisual繪製曲線的方 ...
  • 如果你在自定義的 Main 方法中直接使用 App 類並啟動應用程式,但發現 App.xaml 中定義的資源沒有被正確載入,那麼問題可能在於如何正確配置 App.xaml 與你的 App 類的交互。 確保 App.xaml 文件中的 x:Class 屬性正確指向你的 App 類。這樣,當你創建 Ap ...
  • 一:背景 1. 講故事 上個月有個朋友在微信上找到我,說他們的軟體在客戶那邊隔幾天就要崩潰一次,一直都沒有找到原因,讓我幫忙看下怎麼回事,確實工控類的軟體環境複雜難搞,朋友手上有一個崩潰的dump,剛好丟給我來分析一下。 二:WinDbg分析 1. 程式為什麼會崩潰 windbg 有一個厲害之處在於 ...
  • 前言 .NET生態中有許多依賴註入容器。在大多數情況下,微軟提供的內置容器在易用性和性能方面都非常優秀。外加ASP.NET Core預設使用內置容器,使用很方便。 但是筆者在使用中一直有一個頭疼的問題:服務工廠無法提供請求的服務類型相關的信息。這在一般情況下並沒有影響,但是內置容器支持註冊開放泛型服 ...
  • 一、前言 在項目開發過程中,DataGrid是經常使用到的一個數據展示控制項,而通常表格的最後一列是作為操作列存在,比如會有編輯、刪除等功能按鈕。但WPF的原始DataGrid中,預設只支持固定左側列,這跟大家習慣性操作列放最後不符,今天就來介紹一種簡單的方式實現固定右側列。(這裡的實現方式參考的大佬 ...