模組化與 Library


Posted by saffran on 2021-02-05

借別人的東西來用:require

Module 模組

(Module 中國翻譯叫做“模塊”)
Module 就是「一個功能」

如果沒有 Module 的概念,那就會像這樣:把所有功能都放在一起
壞處是:每個功能之間依賴性太高,變得很難維護(改一個就動到另一個)

因此比較好的做法是「模組化」把功能切分開來:

  • 有一個「登入功能」的 module
  • 有一個「金流功能」的 module
  • 有一個「會員功能」的 module
  • 有一個「權限功能」的 module

最後用一個主程式,把每個 module 連接起來

模組化(module)在實務上的應用

在實務上,會把一些共同會用到的 function 抽出來放到一個叫做 utils.js 的檔案裡面,在其他各個地方要用到這些 function 時,再 import 進來

好處是:
因為 function 都只會放在 utils.js 這個檔案裡面

一個 function 的可重複使用性很高,且當我想要修改 function 時,就只要去 utils.js 裡面改就可以了

如何使用「別人提供的 module」

Node.js 有提供一些 module 可以使用:
像是其中一個叫做 OS
透過這些 module 可以拿到一些跟作業系統有關的資訊

module 使用方式如下:

  • 宣告一個變數 os (變數名稱可以自己取),用 require 來引入 OS 這個 module
  • 這個 os 變數就代表「OS 這個 module」
  • 小括號裡面填入「module 名稱」(用 string 的型態,因此要用單引號包起來)
var os = require('os')

現在,就可以開始使用 OS 模組了

例如:
使用其中一個 function 叫做 os.platform() 會回傳我的作業系統名稱

var os = require('os')

console.log(os.platform())
// output: darwin

darwin 是 Mac 核心的名稱

把東西借給別人:export

接下來要講的是:
自己要如何做出一個 module,然後讓別人或自己使用

作法如下:

  1. 新增一個檔案叫做 myModule.js,裡面就會放我要做的 module
  2. 假設在這個 module 裡面,我只提供了一個 function 讓人使用,也就是 double 函式
    myModule.js:
    function double(n){
    return n * 2
    }
    

現在,我想要在另一個檔案 index.js 裡面,引入 myModule.js 這個 module 來使用,該怎麼做呢?

方法一 module.exports = double

  1. 在 myModule.js,用 module.exports = double 先把這個 module 「輸出」:
function double(n){
  return n * 2
}

module.exports = double // 輸出 module
  1. 在 index.js 要引入 myModule.js 時,

在 require 小括號裡面,在「module 檔案名稱」前面要加上 ./ (也就是檔案路徑:./ 代表是在同一個資料夾底下),因為這是我自己寫的 module,而不是系統(Node.js)提供的,所以要加上檔案路徑

var myModule = require('./myModule.js')

通常都會把副檔名省略不寫

module 檔案名稱的副檔名(.js)可以省略

var myModule = require('./myModule')

require 很聰明,如果沒寫副檔名的話,它就會自己去找有沒有 .js 的檔案

在 myModule.js「module.exports =」後面接的東西,就會是 index.js「require」進來的東西

(在此範例中,就是指 double 函式)

因此,如果我在 index.js 把 myModule 印出來,結果就會是「double 函式」

var myModule = require('./myModule.js')

console.log(myModule)
// output: [Function: double]

因為現在的 myModule 變數就代表「double 函式」
因此,myModule(6) 就等於是 double(6)

var myModule = require('./myModule')

console.log(myModule(6))
// output: 12

變數名稱可以自己改

例如:我改成叫做 calc

var calc = require('./myModule')

console.log(calc(6))
// output: 12

可以 export 任何東西(數字、陣列、字串...都可以)

例如:我在 myModule.js export 一個陣列 [7, 8, 9]

function double(n){
  return n * 2
}

module.exports = [7, 8, 9] // 輸出 module

那在 index.js 就會引入這個 [ 7, 8, 9 ] 陣列

var myModule = require('./myModule')

console.log(myModule)
// output: [ 7, 8, 9 ]

同時 export 很多個 function

通常,一個 module 裡面都會提供很多個 function,那要如何同時輸出這些 function 呢?

作法是:

export 一個物件 obj,裡面放入所有我要輸出的 function

在物件 obj 裡面:

  • key 是 double(可以自己隨意取名),value 是 double (也就是 double 函式)
  • key 是 triple(可以自己隨意取名),value 是 triple 函式
function double(n){
  return n * 2
}

var obj = {
  double: double,
  triple: function(n){
    return n * 3
  }
}

module.exports = obj

現在,我就可以在 index.js 裡面,使用 module 所有的 function 了

先把 module 印出來看看,結果當然也會是一個物件:

var myModule = require('./myModule')

console.log(myModule)
// output: { double: [Function: double], triple: [Function: triple] }

用物件的 key 來取用 function:

var myModule = require('./myModule')

console.log(myModule.double(4), myModule.triple(7))
// output: 8 21

為什麼可以這樣用?

背後運作的原理是:
因為這時的變數 myModule 就等同於是 obj 物件,像是這樣

var myModule = {
  double: double,
  triple: function (n) {
    return n * 3
  }
}

console.log(myModule.double(4), myModule.triple(7))

方法二 exports.double = double

在 myModule.js 除了使用 module.exports = double 來輸出之外,Node.js 提供了第二種寫法是 exports.double = double

myModule.js:

exports 本身當作一個空物件 {},輸出的東西就是一個物件

  • exports. 後面接的會是「物件的 key 名稱」(自己隨意取名)
  • 等號後面接 function 名稱 double(就會是 hello 這個 key 的 value)
    ```javascript=
    function double(n){
    return n * 2
    }

exports.hello = double


index.js:
把 myModule 印出來一樣會是一個物件
* key 是 hello
* value 是 double 函式
```javascript=
var myModule = require('./myModule')

console.log(myModule)
// output: { hello: [Function: double] }

輸出多個 function

也可以再 export 另一個函式
myModule.js:

function double(n){
  return n * 2
}

exports.hello = double
exports.triple = function(n){
  return n * 3
}

背後運作的原理:

exports 本身當作一個空物件 {}
所以在執行完 exports.hello = doubleexports.triple = function(n){ return n * 3 } 之後,exports 物件就會像是這樣:

{
  hello: double,
  triple: function(n){
    return n * 3
  }
}

index.js:
把 myModule 印出來一樣會是一個物件,裡面有兩個 function

var myModule = require('./myModule')

console.log(myModule)
// output: { hello: [Function: double], triple: [Function] }

兩種方法的差別在於:

使用 module.exports = 789 的話,= 後面可以接任何東西(數字、字串、陣列、物件...都可以),也就是說:可以輸出任何東西(數字、字串、陣列、物件…都可以)

function double(n){
  return n * 2
}

module.exports = 789

但如果是使用 exports.hello = double 的話,輸出的就一定會是一個「物件」

function double(n){
  return n * 2
}

exports.hello = double
exports.triple = function(n){
  return n * 3
}

#javascript







Related Posts

淺談 React 中的 State 與 Props

淺談 React 中的 State 與 Props

Bootstrap5 如何安裝及檢測

Bootstrap5 如何安裝及檢測

MTR04_1105

MTR04_1105


Comments