對於JS模組的簡單瞭解

luckyzv發表於2019-02-16

require、import、export

CommonJS規範

require()和module.exports

使用立即執行函式的寫法,外部程式碼無法讀取內部的_count變數

let module = (function() {
    let _count = 0
    let m1 = function() {
      console.log(_count)
    }
    
    let m2 = function() {
      console.log(_count + 1)
    }
    
    return {
        m1: m1,
        m2: m2
    }
})

ES6規範

  • 使用export匯出,用於規定模組的對外介面

一個模組是一個獨立檔案,檔案內的所有變數或函式或類外部無法獲取,如果希望獲取到,必須使用export關鍵字

(1) 輸出變數或者函式、類

輸出變數

// profile.js
export let firstName = `Mc`
export let lastName = `IU`
export const year = 2017 

另一種寫法,優先考慮下面這種寫法

let firstName = `Mc`
let lastName = `IU`
const year = 2017

export {firstName, lastName, year}

輸出一個函式

function v1() { }
function v2() { }
export {
    v1 as namedV1, // as關鍵字重新命名
    v2
}

(2) export語句輸出的介面,與其對應的值是動態繫結關係,可以取到模組內部實時的值

export let foo = `baz`
setTimeout(() => foo = `baz`, 500)
// 輸出foo值為bar,500毫秒之後變為baz

(3) export default命令,預設輸出

// default.js

// 匿名函式
export default function() {
  console.log(`foo`)
}

// 非匿名函式
export default function foo() {
  console.log(`foo`)
}

// 另一種寫法
function foo() {
  console.log(`foo`)
}

export default foo

default後不能跟變數宣告語句

// 錯誤
// export default let a = 1
let a = 1
export default a

輸出類

export default class {}

import Name from `Myclass`
let o = new Name()

(4) 需要注意的正確的寫法

// 錯誤寫法
// ①export 1
// ②let m = 1; export m

// 變數的export正確寫法
export let m = 1

let m = 1
export {m}

let n = 1
export {n as m}

// 函式或類export正確寫法
export function f() {}

function f() {}
export {f}
  • 使用import匯入,用於獲取其他模組提供的功能

使用export命令定義了模組的對外介面後,其他JS檔案就可以通過import來載入這個模組

(1) 引入變數

// main.js
import {firstName, lastName, year} from `./profile`

function setName(element) {
  element.textContent = firstName + ` ` + lastName
}
// 同樣可重新命名
import {lastName as listame} from `./profile`

(2) import具有提升效果

foo()
import {foo} from `my_module` // 不會報錯,可正常呼叫foo函式

(3) 整體載入

// circle.js
function area(radius) {
  return Math.PI * radius * radius
}
function circumference(radius) {
  return 2 * Math.PI * radius
}
// main.js
import {area, circumference} from `./circle` // 逐個載入

area(4)
circumference(14)

import * as circle from `./circle` // 整體載入

circle.area(4)
circle.circumference(14)

(4) 引入預設匯出

// 預設匯出
export default function crc32() {}

import anyName from `crc32`

// 非預設匯出(注意大括號)
export function crc32() {}

import {crc32} from `crc32`
  • 模組的繼承

假設有一個circleplus模組,繼承了circle模組:

// circleplus.js
export * from `circle` // 繼承了circle的所有屬性和方法
export let e = 2.718

export default function(x) {
  return Math.exp(x)
}

上面程式碼中的export ,表示再輸出circle模組的所有屬性和方法。注意export 命令會忽略circle模組的default方法。
然後,上面程式碼又輸出了自定義的e變數和預設方法。

這時,也可以將circle的屬性或方法,改名後再輸出:

// circleplus.js
export {area as circleArea} from `cricle`

上面程式碼表示,只輸出circle模組的area方法,且將其改名為circleArea。

載入方法如下

// math.js
import * as math from `circleplus`

import exp from `circleplus`

console.log(exp(math.e))

相關文章