久久久久久久视色,久久电影免费精品,中文亚洲欧美乱码在线观看,在线免费播放AV片

<center id="vfaef"><input id="vfaef"><table id="vfaef"></table></input></center>

    <p id="vfaef"><kbd id="vfaef"></kbd></p>

    
    
    <pre id="vfaef"><u id="vfaef"></u></pre>

      <thead id="vfaef"><input id="vfaef"></input></thead>

    1. 站長資訊網(wǎng)
      最全最豐富的資訊網(wǎng)站

      一文帶你了解node中的的模塊系統(tǒng)

      本篇文章帶大家進(jìn)行node學(xué)習(xí),深入淺出的了解node中的的模塊系統(tǒng),希望對大家有所幫助!

      一文帶你了解node中的的模塊系統(tǒng)

      兩年前寫過一篇文章介紹模塊系統(tǒng):理解前端模塊概念:CommonJs與ES6Module。這篇文章的知識面都是針對剛?cè)腴T的,比較淺顯。在這也糾正文章的幾個錯誤:

      • 【模塊】和【模塊系統(tǒng)】 是兩碼事。模塊是軟件中的一個單元,而模塊系統(tǒng)則是一套語法或者工具,模塊系統(tǒng)能讓開發(fā)者在項目中定義和使用模塊。
      • ECMAScript Module縮寫是ESM,或者ESModule,而不是ES6Module。

      關(guān)于模塊系統(tǒng)的基礎(chǔ)知識都在上一篇文章說的差不多了,所以這篇文章會重點(diǎn)關(guān)注模塊系統(tǒng)的內(nèi)部原理以及更加完整的介紹不同模塊系統(tǒng)之間的區(qū)別,上一篇文章出現(xiàn)的內(nèi)容在這就不再重復(fù)了?!鞠嚓P(guān)教程推薦:nodejs視頻教程、編程教學(xué)】

      模塊系統(tǒng)

      并不是所有編程語言都有內(nèi)置的模塊系統(tǒng),JavaScript誕生之后的很長一段時間里都沒有模塊系統(tǒng)。

      在瀏覽器環(huán)境中只能使用<script>標(biāo)簽來引入不用的代碼文件,這種方法共享一個全局作用域,可謂是問題多多;加上前端日新月異的發(fā)展,這種方法已經(jīng)不滿足當(dāng)下的需求了。在沒官方的模塊系統(tǒng)出現(xiàn)前,前端社區(qū)自己創(chuàng)建第三方模塊系統(tǒng),用的較多的有:異步模塊定義AMD、通用模塊定義UMD等,當(dāng)然最著名還得是CommonJS。

      由于Node.js它是一個JavaScript的運(yùn)行環(huán)境,可以直接訪問底層的文件系統(tǒng)。所以開發(fā)者通過它,并按照CommonJS規(guī)范實現(xiàn)了一套模塊系統(tǒng)。

      最開始,CommonJS只能用于Node.js平臺,隨著Browserify和Webpack之類的模塊打包工具的出現(xiàn),CommonJS也終于能在瀏覽器端運(yùn)行了。

      到2015年發(fā)布了ECMAScript6規(guī)范,才有了模塊系統(tǒng)的正式標(biāo)準(zhǔn),按照該標(biāo)準(zhǔn)打造出來的模塊系統(tǒng)稱為ECMAScript module簡稱【ESM】,由此ESM就開始統(tǒng)一了Node.js環(huán)境與瀏覽器環(huán)境。當(dāng)然ECMAScript6只是提供了語法和語義,至于實現(xiàn)部分得由各瀏覽器服務(wù)廠商和Node開發(fā)者去努力。所以才有了令其他編程語言羨慕不已的babel神器,實現(xiàn)模塊系統(tǒng)并不是一件容易的事,Node.js也是到了13.2版本才算是比較穩(wěn)定的支持ESM。

      但不管怎么樣,ESM才是JavaScript的“親兒子”,學(xué)習(xí)它一定不會有錯!

      模塊系統(tǒng)的基本思路

      在刀耕火種的年代中使用JavaScript開發(fā)應(yīng)用,腳本文件只能通過script標(biāo)簽引入。其中遇到比較嚴(yán)重的問題就是缺乏命名空間機(jī)制,這意味著每個腳本都共享同一作用域。這個問題在社區(qū)中有一個比較好的解決方法:Revevaling module

      const myModule = (() => {     const _privateFn = () => {}     const _privateAttr = 1     return {         publicFn: () => {},         publicAttr: 2     } })()  console.log(myModule) console.log(myModule.publicFn, myModule._privateFn)
      登錄后復(fù)制

      運(yùn)行結(jié)果如下:

      一文帶你了解node中的的模塊系統(tǒng)

      這個模式很簡單,利用IIFE創(chuàng)建一個私有的作用域,同時使用return需要暴露的變量。而屬于內(nèi)部的變量(比如_privateFn、_privateAttr)是不能從外面的作用域訪問的。

      【revealing module】正是利用了這些特性,來隱藏私有的信息,同時把應(yīng)該公布給外界的API導(dǎo)出。后面的模塊系統(tǒng)也正是基于這樣的思路開發(fā)的。

      CommonJS

      基于上面思路,來開發(fā)一個模塊加載器。

      首先編寫一個加載模塊內(nèi)容的函數(shù),并把這個函數(shù)包裹在私有作用域里面,然后通過eval()求值,以運(yùn)行該函數(shù):

      function loadModule (filename, module, require) {   const wrappedSrc =      `(function (module, exports, require) {       ${fs.readFileSync(filename, 'utf8)}     }(module, module.exports, require)`   eval(wrappedSrc) }
      登錄后復(fù)制

      和【revealing module】一樣,把模塊的源代碼包裹在函數(shù)里面,區(qū)別在于,還把一系列變量(module, module.exports, require)傳給該函數(shù)。

      值得注意的是,通過【readFileSync】讀取模塊內(nèi)容。一般來說,在調(diào)用涉及文件系統(tǒng)的API時,不應(yīng)該使用同步版本。但此時不同,因為通過CommonJs系統(tǒng)來加載模塊,本身就應(yīng)該實現(xiàn)成同步操作,以確保多個模塊能夠按照正確的依賴順序得到引入。

      接著模擬require()函數(shù),主要功能是加載模塊。

      function require(moduleName) {   const id = require.resolve(moduleName)   if (require.cache[id]) {     return require.cache[id].exports   }   // 模塊的元數(shù)據(jù)   const module = {     exports: {},     id   }   // 更新緩存   require.cache[id] = module      // 載入模塊   loadModule(id, module, require)      // 返回導(dǎo)出的變量   return module.exports } require.cache = {} require.resolve = (moduleName) => {   // 根據(jù)moduleName解析出完整的模塊id }
      登錄后復(fù)制

      (1)函數(shù)接收到moduleName后,首先解析出模塊的完整路徑,賦值給id。
      (2)如果cache[id]為true,說明該模塊已經(jīng)被加載過了,直接返回緩存結(jié)果
      (3)否則,就配置一套環(huán)境,用于首次加載。具體來說,創(chuàng)建module對象,包含exports(也就是導(dǎo)出內(nèi)容),id(作用如上)
      (4)將首次加載的module緩存起來
      (5)通過loadModule從模塊的源文件中讀取源代碼
      (6)最后return module.exports返回想要導(dǎo)出的內(nèi)容。

      require是同步的

      在模擬require函數(shù)的時候,有一個很重要的細(xì)節(jié):require函數(shù)必須是同步的。它的作用僅僅是直接將模塊內(nèi)容返回而已,并沒有用到回調(diào)機(jī)制。Node.js中的require也是如此。所以針對module.exports的賦值操作,也必須是同步的,如果用異步就會出問題:

      // 出問題 setTimeout(() => {     module.exports = function () {} }, 1000)
      登錄后復(fù)制

      require是同步函數(shù)這一點(diǎn)對定義模塊的方式有著非常重要的影響,因為它迫使我們在定義模塊時只能使用同步的代碼,以至于Node.js都為此,提供了大多數(shù)異步API的同步版本。

      早期的Node.js有異步版本的require函數(shù),但很快就移除了,因為這會讓函數(shù)的功能變得十分復(fù)雜。

      ESM

      ESM是ECMAScript2015規(guī)范的一部分,該規(guī)范給JavaScript語言指定了一套官方的模塊系統(tǒng),以適應(yīng)各種執(zhí)行環(huán)境。

      在Node.js中使用ESM

      Node.js默認(rèn)會把.js后綴的文件,都當(dāng)成是采用CommonJS語法所寫的。如果直接在.js文件中采用ESM語法,解釋器會報錯。

      有三種方法可以在讓Node.js解釋器轉(zhuǎn)為ESM語法:
      1、把文件后綴名改為.mjs;
      2、給最近的package.json文件添加type字段,值為“module”;
      3、字符串作為參數(shù)傳入--eval,或通過STDIN管道傳輸?shù)絥ode,帶有標(biāo)志--input-type=module
      比如:

      node --input-type=module --eval "import { sep } from 'node:path';  console.log(sep);"
      登錄后復(fù)制

      不同類型模塊引用

      ESM可以被解析并緩存為URL(這也意味著特殊字符必須是百分比編碼)。支持file:、node:data:等的URL協(xié)議

      file:URL
      如果用于解析模塊的import說明符具有不同的查詢或片段,則會多次加載模塊

      // 被認(rèn)為是兩個不同的模塊 import './foo.mjs?query=1'; import './foo.mjs?query=2';
      登錄后復(fù)制

      data:URL
      支持使用MIME類型導(dǎo)入:

      • text/javascript用于ES模塊
      • application/json用于JSON
      • application/wasm用于Wasm

      import 'data:text/javascript,console.log("hello!");'; import _ from 'data:application/json,"world!"' assert { type: 'json' };
      登錄后復(fù)制

      data:URL僅解析內(nèi)置模塊的裸說明符和絕對說明符。解析相對說明符不起作用,因為data:不是特殊協(xié)議,沒有相對解析的概念。

      導(dǎo)入斷言
      這個屬性為模塊導(dǎo)入語句添加了內(nèi)聯(lián)語法,以便在模塊說明符旁邊傳入

      贊(0)
      分享到: 更多 (0)
      網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號