JS模組化

冰大墩發表於2022-12-04

模組化規範

1.CommonJS規範

​ 在node中,預設支援的模組化規範叫做CommonJS,

​ 在CommonJS中,一個js檔案就是一個模組

  • CommonJS規範

    • 引入模組

      • 使用require('模組的路徑')函式來引入模組

      • 引入自定義模組時

        • 模組名要以 ./ 或 ../ 開頭
        • 副檔名可以省略
          • 在CommonJS中,如果省略的js檔案的副檔名,node會自動不全副檔名
            • 如果沒有改js檔案,會找名字相同的檔案進行引入
      • 引入核心模組時

        • 直接寫核心模組的名字即可
        • 也可以在核心模組前新增node:可以加快查詢效率
    //引入自定義模組
    const m1 = require("./m1")
    //按需引入
    const name = require('./m1').name
    const {name,age,gender} = require('./m1')
    //引入核心模組
     const path = require("path")
     const path = require("node:path")
    

    在定義模組時,模組中的內容預設是不能被外部看到的

    ​ 可以透過exports來設定要向外部暴露的內容

    訪問exports的方式有兩種:

    1. exports
    2. module.exports
    • 當我們在其他模組中引入當前模組時,require函式返回的就是exports -
    • 可以將希望暴露給外部模組的內容設定為exports的屬性
    ------------------------------m1.js----------------------------------------
    // 可以透過exports 一個一個的匯出值
    // exports.a = "孫悟空"
    // exports.b = {name:"白骨精"}
    // exports.c = function fn(){
    //     console.log("哈哈")
    // }
    
    // 也可以直接透過module.exports同時匯出多個值
    module.exports = {
        a: "哈哈",
        b: [1, 3, 5, 7],
        c: () =>{
            console.log(111)
        }
    }
    
    

    CommonJS執行原理:

    1. 所有的CommonJS的模組都會被包裝到一個函式中

      (function(exports, require, module, __filename, __dirname){
          //模組程式碼會被放到這裡
      })
      

      exports:用來設定模組向外部暴露的內容

      require:用來引入模組的方法

      module:當前模組的引用

      __filename:模組的路徑

      __dirname:模組所在目錄的路徑

2.ES6模組化

Node.js中同樣支援ES模組化,使用模組化無非就是需要注意兩件事匯出和匯入

  1. 匯出

    // 匯出變數(命名匯出)
    export let name1, name2, …, nameN; 
    export let name1 = …, name2 = …, …, nameN; 
    ​
    // 匯出函式(命名匯出)
    export function functionName(){...}
    ​
    // 匯出類(命名匯出)
    export class ClassName {...}
    ​
    // 匯出一組
    export { name1, name2, …, nameN };
    ​
    // 重新命名匯出
    export { variable1 as name1, variable2 as name2, …, nameN };
    ​
    // 解構賦值後匯出
    export const { name1, name2: bar } = o;
    ​
    // 預設匯出
    export default expression;
    export default function (…) { … } // also class, function*
    export default function name1(…) { … } // also class, function*
    export { name1 as default, … };
    ​
    // 聚合模組
    export * from …; // 將其他模組中的全部內容匯出(除了default)
    export * as name1 from …; // ECMAScript® 2O20 將其他模組中的全部內容以指定別名匯出
    export { name1, name2, …, nameN } from …; // 將其他模組中的指定內容匯出
    export { import1 as name1, import2 as name2, …, nameN } from …; // 將其他模組中的指定內容重新命名匯出
    export { default, … } from …; 
    
  2. 引入

    // 引入預設匯出
    import defaultExport from "module-name";
    ​
    // 將所有模組匯入到指定名稱空間中
    import * as name from "module-name";
    ​
    // 引入模組中的指定內容
    import { export1 } from "module-name";
    import { export1 , export2 } from "module-name";
    ​
    // 以指定別名引入模組中的指定內容
    import { export1 as alias1 } from "module-name";
    import { export1 , export2 as alias2 , [...] } from "module-name";
    ​
    // 引入預設和其他內容
    import defaultExport, { export1 [ , [...] ] } from "module-name";
    import defaultExport, * as name from "module-name";
    ​
    // 引入模組
    import "module-name";
    

    需要注意的是,Node.js預設並不支援ES模組化,如果需要使用可以採用兩種方式:

    1. 方式一:直接將所有js檔案修改為mjs副檔名。
    2. 方式二:修改package.json中type屬性為module。

3.核心模組

核心模組,是node中自帶的模組,可以在node中直接使用

  1. window 是瀏覽器的宿主物件 node中是沒有的
  2. global 是node中的全域性物件,作用類似於window
  3. ES標準下,全域性物件的標準名應該是 globalThis
  • process

    • 表示當前的node程式

    • 可以透過改物件獲取程式的資訊,或者對程式做各種操作

    • 如何使用

      1. process是一個全域性變數,可以直接使用

      2. 有哪些屬性和方法:

        1. process.exit([code狀態碼])

          1. 結束當前程式,終止node
        2. process.nextTick(callback[ ...args])

          1. 將函式插入到 tick佇列中

          2. tick佇列中的程式碼,會在下一次事件迴圈之前執行,會在微任務佇列和宏任務佇列中任務之前執行

            setTimeout(()=>{
            	console.log('111')
            }) //宏任務佇列
            queueMicrotask(()=>{
                console.log('222')
            })  //微任務佇列
            process.nextTick(()=>{
                console.log('333')
            })
            console.log('444')
            
            
            //執行順序為: 444 -> 333 -> 222 -> 111
            

      執行順序:

      1. 呼叫棧
      2. tick佇列(瞭解)
      3. 微任務佇列
      4. 宏任務佇列
  • path模組

    • 表示的路徑

    • 透過path可以用來獲取各種路徑

    • 要使用path,需要先對其進行引入

    • 方法:

      • path.resolve([...paths])

        • 用來生成一個絕對路徑
        • 直接呼叫resolve,則返回當前的工作目錄
        • 注意,我們透過不同的方式執行程式碼時,它的工作目錄是有可能發生變化的
      • 如果將一個相對路徑作為引數:

        • 則resolve會自動將其轉換為絕對路徑
        • 此時根據工作目錄的不同,他所產生的絕對路徑也不同
      • 一般會將一個絕對路徑作為第一個引數

        • 一個相對路徑作為第二個引數
        • 這樣它會自動計算出最後的路徑
      //引入模組
      const path = require('node:path')
      //以後在使用路徑時,儘量透過path.resolve()來生成路徑
      const result = path.resolve(__dirname, './hello.js')
      
  • fs模組

    • fs用來幫助node來操作磁碟中的檔案

    • 檔案操作也就是所謂的I/O流,input output

    • 使用fs模組,同樣需要引入

    • fs.readFileSync()

      • readFileSync() 同步的讀取檔案的方法,會阻塞後面的程式碼執行

      • 當我們透過fs模組讀取磁碟中的資料時,讀取到的資料總會一Buffer物件的形式返回

      • Buffer是一個臨時用來儲存資料的緩衝區

        //引入模組
        const path = require('node:path')
        const fs = require('node:fs')
        const buffer = fs.readFileSync(path.resolve(__dirname, './hello.txt'))
        console.log(buffer.toString())  //把Buffer資料轉換為字串型別
        
    • fs.readFile()

      • 非同步的讀取檔案的方法

        • 方法1:回撥函式式

          const path = require('node:path')
          const fs = require('node:fs')
          fs.readFile(path.resolve(__dirname, './hello.js'),(err,buffer)=>{
              if(err){
                   console.log("出錯了~")
              } else {
                   console.log(buffer.toString())
              }
          })
          
        • 方法2:promise式

          const path = require('node:path')
          const fs = require('node:fs/promises')
          fs.readFile(path.resolve(__dirname, './hello.js'))
          	.then(buffer=>{
              	console.log(buffer.toString())
          	})
          	.catch(e=>{
              	console.log('出錯了,有問題', e.message)
          	})
          
        • 方法3:async和await式

          ;(async ()=>{
              try {
                  const buffer = await fs.readFile(path.resolve(__dirname, './hello.js'))
                  console.log(buffer.toString())
              } catch(e){
                  console.log(’出錯了....)
              }
          })()
          
    • fs.appendFile()

      • 建立新檔案,或將資料新增到已有檔案中
    • fs.mkdir()

      • 建立目錄
    • fs.rmdir()

      • 刪除目錄
    • fs.rm()

      • 刪除目錄
    • fs.rename()

      • 重新命名
    • fs.copyFile()

      • 複製檔案
  1. //實現複製一個檔案
    //1.讀取檔案中的內容
    const path = require('node:path')
    const fs = require('node:fs/promises')
    fs.readFile(path.reslove(__dirname, './hello.txt'))
    	.then(buffer =>{
        	//2.複製檔案中的
        	return fs.appendFile(path.resolve(__dirname, './world.txt'), buffer)
    	})
    	.then(()=>{
        	console.log('操作結束')
    	})
    	.catch(err =>{
        	console.log('出錯了..')
    	})
    

相關文章