ES6之Module 的加载实现(1)
1.瀏覽器加載
1.1傳統方法:
在 HTML 網頁中,瀏覽器通過<script>標簽加載 JavaScript 腳本
默認情況下,瀏覽器是同步加載 JavaScript 腳本,即渲染引擎遇到<script>標簽就會停下來,等到執行完腳本,再繼續向下渲染。如果是外部腳本,還必須加入腳本下載的時間
如果腳本體積很大,下載和執行的時間就會很長,因此造成瀏覽器堵塞,用戶會感覺到瀏覽器“卡死”了,沒有任何響應。這顯然是很不好的體驗,所以瀏覽器允許腳本異步加載,下面就是兩種異步加載的語法
上面代碼中,<script>標簽打開defer或async屬性,腳本就會異步加載。渲染引擎遇到這一行命令,就會開始下載外部腳本,但不會等它下載和執行,而是直接執行后面的命令
defer與async的區別是:前者要等到整個頁面正常渲染結束,才會執行;后者一旦下載完,渲染引擎就會中斷渲染,執行這個腳本以后,再繼續渲染。一句話,defer是“渲染完再執行”,async是“下載完就執行”。另外,如果有多個defer腳本,會按照它們在頁面出現的順序加載,而多個async腳本是不能保證加載順序的
1.2加載規則:
瀏覽器加載 ES6 模塊,也使用<script>標簽,但是要加入type=”module”屬性
上面代碼在網頁中插入一個模塊foo.js,由于type屬性設為module,所以瀏覽器知道這是一個 ES6 模塊
瀏覽器對于帶有type=”module”的<script>,都是異步加載,不會造成堵塞瀏覽器,即等到整個頁面渲染完,再執行模塊腳本,等同于打開了<script>標簽的defer屬性
<script>標簽的async屬性也可以打開,這時只要加載完成,渲染引擎就會中斷渲染立即執行。執行完成后,再恢復渲染
ES6 模塊也允許內嵌在網頁中,語法行為與加載外部腳本完全一致
對于外部的模塊腳本(上例是foo.js),有幾點需要注意
- 代碼是在模塊作用域之中運行,而不是在全局作用域運行。模塊內部的頂層變量,外部不可見
- 模塊腳本自動采用嚴格模式,不管有沒有聲明use strict
- 模塊之中,可以使用import命令加載其他模塊(.js后綴不可省略,需要提供絕對 URL 或相對 URL),也可以使用export命令輸出對外接口
- 模塊之中,頂層的this關鍵字返回undefined,而不是指向window。也就是說,在模塊頂層使用this關鍵字,是無意義的
- 同一個模塊如果加載多次,將只執行一次
下面是一個示例模塊
利用頂層的this等于undefined這個語法點,可以偵測當前代碼是否在 ES6 模塊之中
2.ES6 模塊與 CommonJS 模塊的差異
- CommonJS 模塊輸出的是一個值的拷貝,ES6 模塊輸出的是值的引用
- CommonJS 模塊是運行時加載,ES6 模塊是編譯時輸出接口
第二個差異是因為 CommonJS 加載的是一個對象(即module.exports屬性),該對象只有在腳本運行完才會生成。而 ES6 模塊不是對象,它的對外接口export只是一種靜態定義,在代碼靜態解析階段就會生成
下面重點解釋第一個差異
CommonJS 模塊輸出的是值的拷貝,也就是說,一旦輸出一個值,模塊內部的變化就影響不到這個值。請看下面這個模塊文件lib.js的例子
ES6 模塊的運行機制與 CommonJS 不一樣。JS 引擎對腳本靜態分析的時候,遇到模塊加載命令import,就會生成一個對輸出模塊的只讀引用,等到腳本真正要用到模塊輸出的方法時,再根據這個只讀引用,到被加載的那個模塊里面去取值。換句話說,ES6 的import有點像 Unix 系統的“符號連接”,原始值變了,import加載的值也會跟著變。因此,ES6 模塊是動態引用,并且不會緩存值,模塊里面的變量綁定其所在的模塊
上面代碼說明,ES6 模塊輸入的變量counter是活的,完全反應其所在模塊lib.js內部的變化
上面代碼表明,ES6 模塊不會緩存運行結果,而是動態地去被加載的模塊取值,并且變量總是綁定其所在的模塊
由于 ES6 輸入的模塊變量,只是一個“符號連接”,所以這個變量是只讀的,對它進行重新賦值會報錯
上面代碼中,main.js從lib.js輸入變量obj,可以對obj添加屬性,但是重新賦值就會報錯。因為變量obj指向的地址是只讀的,不能重新賦值,這就好比main.js創造了一個名為obj的const變量
最后,export通過接口,輸出的是同一個值。不同的腳本加載這個接口,得到的都是同樣的實例
這就證明了x.js和y.js加載的都是C的同一個實例
總結
以上是生活随笔為你收集整理的ES6之Module 的加载实现(1)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android t类型参数,androi
- 下一篇: html桌面图标样式,如何更改图标样式,