點燈坊

學而時習之,不亦悅乎

ECMAScript 之 CommonJS Module

Sam Xiao's Avatar 2019-12-01

雖然前端都使用 ECMAScript 2015 定義的 ES Module,但後端 Node 進度則較慢,還是不少仍使用 CommonJS Module,因此了解 CommonJS 還是必須的。

Version

macOS Catalina 10.15.1
VS Code 1.40.1
Quokka 1.0.261

Variable

let title = 'FP in JavaScript'
let price = 100

module.exports = {
  title,
  price
}

可先定義 variable 後再使用 object literal 組合傳給 module.exports

let myModule = require('./myModule')

myModule.title // ?
myModule.price // ?

使用 require() 接收整個 object 並使用 . 存取 variable。

common000

exports.title = 'FP in JavaScript'
exports.price = price = 100

CommonJS 另外提供更精簡寫法,exports 相當於 module.exports,因此可直接對 exports 新增 titleprice property 即可。

let { title, price } = require('./myModule')

title // ?
price // ?

由於 require() 回傳為 object,可直接使用 ES6 的 {} object destructuring 加以解構。

common001

Object

let obj = {
  title: 'FP in JavaScript',
  price: 100
}

module.exports = obj

module.exports 原本就需要 object,因此將 obj 直接指定給 module.exports 即可。

let myModule = require('./myModule')

myModule.title // ?
myModule.price // ?

使用 require() 接收整個 object 並使用 . 存取 variable。

common001

module.exports = {
  title: 'FP in JavaScript',
  price: 100
}

也可將 object literal 直接指定給 module.exports

let { title, price } = require('./myModule')

title // ?
price // ?

由於 require() 回傳為 object,可直接使用 ES6 的 {} object destructuring 加以解構。

common003

Function

function add(x, y) {
  return x + y
}

module.exports = {
  add
}

可先定義好 function,但 module.exports 要求為 object,因此使用 ES6 的 property shorthand 組合 object 回傳。

let myModule = require('./myModule')

myModule.add(1, 1) // ?

使用 require() 接收整個 object 並使用 . 存取 function。

common007

function add(x, y) {
  return x + y
}

exports.add = add

由於 exports 相當於 module.exports,因此也可使用 exports 動態新增 property 方式回傳 function。

common004

exports.add = (x, y) => x + y

exports 也可直接搭配 arrow function。

let { add } = require('./myModule')

add(1, 1) // ?

可直接使用 object destructuring 將 function 取出。

common005

Class

class Counter {
  constructor(x, y) {
    this.x = x
    this.y = y
  }

  sum() {
    return this.x + this.y
  }
}

module.exports = Counter

將 class 傳給 module.exports

let Counter = require('./myModule')

let counter = new Counter(1, 1)
counter.sum() // ?

require() 後回傳為 class,可直接使用。

common006

Conclusion

  • 關於 object export 部分,CommonJS 比 ES Module 優,CommonJS 可直接 export object,並在 require 直接使用 object destructuring 解構,但 import 卻沒有辦法一次到位,因為 ES Module 會多包一層 object
  • Object 與 class 在實務上常使用 module.exports,variable 與 function 則使用 exports 較為精簡
  • Variable、Object 與 function 在 require() 時常直接搭配 object destructuring 加以解構

Reference

Ruhan Khandakar, Introducting module.exports | How to export in Node.js