您好,登錄后才能下訂單哦!
本文小編為大家詳細(xì)介紹“es6模塊輸出的值是不是拷貝的”,內(nèi)容詳細(xì),步驟清晰,細(xì)節(jié)處理妥當(dāng),希望這篇“es6模塊輸出的值是不是拷貝的”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來(lái)學(xué)習(xí)新知識(shí)吧。
不是,ES6模塊輸出的是值的引用,CommonJS模塊輸出的才是一個(gè)值的拷貝。在ES6模塊中,JS引擎對(duì)腳本靜態(tài)分析的時(shí)候,遇到模塊加載命令import,就會(huì)生成一個(gè)只讀引用;等到腳本真正執(zhí)行時(shí),再根據(jù)這個(gè)只讀引用,到被加載的那個(gè)模塊里面去取值。ES6模塊是動(dòng)態(tài)引用,ES6模塊不會(huì)緩存運(yùn)行結(jié)果,而是動(dòng)態(tài)地去被加載的模塊取值,并且變量總是綁定其所在的模塊。
默認(rèn)情況下,瀏覽器是同步加載 JavaScript 腳本的,即渲染引擎遇到
<script>
標(biāo)簽就會(huì)停下來(lái),等到執(zhí)行完腳本,再繼續(xù)向下渲染。
如果是外部腳本,還必須加入腳本下載的時(shí)間。
如果腳本體積很大,下載和執(zhí)行的時(shí)間就會(huì)很長(zhǎng),因此造成瀏覽器堵塞,用戶會(huì)感覺(jué)到瀏覽器“卡死”了,沒(méi)有任何響應(yīng)。這顯然是很不好的體驗(yàn),所以瀏覽器允許腳本異步加載,下面就是兩種異步加載的語(yǔ)法。
<script src="path/to/myModule.js" defer></script>
<script src="path/to/myModule.js" async></script>
<script>
標(biāo)簽打開defer或async屬性,腳本就會(huì)異步加載。渲染引擎遇到這一行命令,就會(huì)開始下載外部腳本,但不會(huì)等它下載和執(zhí)行,而是直接執(zhí)行后面的命令。
defer
要等到整個(gè)頁(yè)面在內(nèi)存中正常渲染結(jié)束(DOM 結(jié)構(gòu)完全生成,以及其他腳本執(zhí)行完成),才會(huì)執(zhí)行;
async
一旦下載完,渲染引擎就會(huì)中斷渲染,執(zhí)行這個(gè)腳本以后,再繼續(xù)渲染。
一句話,defer是“渲染完再執(zhí)行”,async是“下載完就執(zhí)行”。另外,如果有多個(gè)defer腳本,會(huì)按照它們?cè)陧?yè)面出現(xiàn)的順序加載,而多個(gè)async腳本是不能保證加載順序的。
瀏覽器加載 ES6 模塊,也使用<script>
標(biāo)簽,但是要加入type="module"
屬性。瀏覽器對(duì)于帶有type="module"
的<script>
,都是異步加載,不會(huì)造成堵塞瀏覽器,即等到整個(gè)頁(yè)面渲染完,再執(zhí)行模塊腳本,等同于打開了
<script type="module" src="./foo.js"></script>
如果網(wǎng)頁(yè)有多個(gè)<script type="module">
,它們會(huì)按照在頁(yè)面出現(xiàn)的順序依次執(zhí)行。
注意:
<script>
標(biāo)簽的async屬性也可以打開,這時(shí)只要加載完成,渲染引擎就會(huì)中斷渲染立即執(zhí)行。執(zhí)行完成后,再恢復(fù)渲染。一旦使用了async屬性,<script type="module">
就不會(huì)按照在頁(yè)面出現(xiàn)的順序執(zhí)行,而是只要該模塊加載完成,就執(zhí)行該模塊。
對(duì)于外部的模塊腳本(上例是foo.js),有幾點(diǎn)需要注意:
代碼是在模塊作用域之中運(yùn)行,而不是在全局作用域運(yùn)行。模塊內(nèi)部的頂層變量,外部不可見。
模塊腳本自動(dòng)采用嚴(yán)格模式,不管有沒(méi)有聲明use strict。
模塊之中,可以使用import命令加載其他模塊(.js后綴不可省略,需要提供絕對(duì) URL 或相對(duì) URL),也可以使用export命令輸出對(duì)外接口。
模塊之中,頂層的this關(guān)鍵字返回undefined
,而不是指向window。也就是說(shuō),在模塊頂層使用this關(guān)鍵字,是無(wú)意義的。
同一個(gè)模塊如果加載多次,將只執(zhí)行一次。
ES6 模塊也允許內(nèi)嵌在網(wǎng)頁(yè)中,語(yǔ)法行為與加載外部腳本完全一致。
<script type="module">
import utils from "./utils.js";
// other code
</script>
CommonJS規(guī)范加載模塊是同步的,也就是說(shuō),只有加載完成,才能執(zhí)行后面的操作。由于Node.js主要用于服務(wù)器編程,模塊文件一般都已經(jīng)存在于本地硬盤,所以加載起來(lái)比較快,不用考慮非同步加載的方式,所以CommonJS規(guī)范比較適用。
但是,如果是瀏覽器環(huán)境,要從服務(wù)器端加載模塊,這時(shí)就必須采用異步模式。
瀏覽器加載 ES6 模塊是異步加載,不會(huì)造成堵塞瀏覽器,即等到整個(gè)頁(yè)面渲染完,再執(zhí)行模塊腳本
CommonJS 模塊
輸出的是值的拷貝,也就是說(shuō),一旦輸出一個(gè)值,模塊內(nèi)部的變化就影響不到這個(gè)值
ES6 模塊
的運(yùn)行機(jī)制與 CommonJS 不一樣。JS 引擎對(duì)腳本靜態(tài)分析的時(shí)候,遇到模塊加載命令import,就會(huì)生成一個(gè)只讀引用。等到腳本真正執(zhí)行時(shí),再根據(jù)這個(gè)只讀引用,到被加載的那個(gè)模塊里面去取值。
換句話說(shuō),ES6 的import有點(diǎn)像 Unix 系統(tǒng)的“符號(hào)連接”,原始值變了,import加載的值也會(huì)跟著變。因此,ES6 模塊是動(dòng)態(tài)引用,ES6 模塊不會(huì)緩存運(yùn)行結(jié)果,而是動(dòng)態(tài)地去被加載的模塊取值,并且變量總是綁定其所在的模塊。
由于 ES6 輸入的模塊變量,只是一個(gè)“符號(hào)連接”,所以這個(gè)變量是只讀的,對(duì)它進(jìn)行重新賦值會(huì)報(bào)錯(cuò)。上面代碼中,main.js從lib.js輸入變量obj,可以對(duì)obj添加屬性,但是重新賦值就會(huì)報(bào)錯(cuò)。因?yàn)樽兞縪bj指向的地址是只讀的,不能重新賦值,這就好比main.js創(chuàng)造了一個(gè)名為obj的const變量。
// lib.js
export let obj = {};
// main.js
import { obj } from './lib';
obj.prop = 123; // OK
obj = {}; // TypeError
此外,export通過(guò)接口,輸出的是同一個(gè)值。不同的腳本加載這個(gè)接口,得到的都是同樣的實(shí)例。
因?yàn)?CommonJS 加載的是一個(gè)對(duì)象(即module.exports屬性),該對(duì)象只有在腳本運(yùn)行完才會(huì)生成。
而 ES6 模塊不是對(duì)象,它的對(duì)外接口只是一種靜態(tài)定義,在代碼靜態(tài)解析階段就會(huì)生成。
讀到這里,這篇“es6模塊輸出的值是不是拷貝的”文章已經(jīng)介紹完畢,想要掌握這篇文章的知識(shí)點(diǎn)還需要大家自己動(dòng)手實(shí)踐使用過(guò)才能領(lǐng)會(huì),如果想了解更多相關(guān)內(nèi)容的文章,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。