ES模組化的匯入和匯出

賀墨於發表於2021-02-06

環境準備

三個檔案 1.htmla.jsb.js,並要能使程式碼在伺服器環境下執行(不然後面會報跨域的錯誤)

1.html

<!DOCTYPE html>
<html lang="zh_CN">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <script src="./a.js"></script>
    <script src="./b.js"></script>
</body>
</html>

a.js

let flag = false

b.js

console.log(flag)

這是三個特別特別簡單的程式碼,然後我們讓他們在伺服器上執行,為了方便我就使用 vscodeLive Server外掛執行程式碼

執行結果

開啟控制檯後,會發現輸出一行 false

模組化

由此可以看出,在js檔案中定義的變數已經汙染了全域性,隨著專案的增大這可能會導致不必要的麻煩

於是我們需要進行如下操作

<script src="a.js" type="module"></script>
<script src="b.js" type="module"></script>

當在 script 標籤上加上 type="module"就代表這個檔案是一個模組,之中定義的屬性在全域性就訪問不到了。

然後我們再看控制檯,就會發現如下的錯誤

image-20210206130439655

這就表明我們在 js 中定義的變數已經不會汙染全域性了

但是有些時候我們還是需要引用不同 js 檔案中的變數的,那麼看下面

export、import

export

在ES6中,不同模組的內容是不會共享的,我們必須將需要的內容通過 export 給暴露出去,如下

a.js

// 1.單個匯出
export var num1 = 1000
export var height = 1.8


// 2.批量匯出
let flag = false
let sum = 100
export {
	flag,sum
}

// 3.匯出方法
export function add(x, y){ return x + y}

// 4.匯出類
export class Person{

  constructor(name, age){
    this.name = name
    this.age = age
  }

  show(){
    console.log(this.name + ' ' + this.age + ' 歲')
  }
}

這裡需要注意的是,批量匯入並不是我們平時認為的ES6增強寫法

export {
	flag,sum
}

如果你認為上面程式碼等於如下的,那就錯了

export {
	flag: flag,
	sum: sum
}

他會報下面的錯誤,並且連編譯器也會認為這個寫法不合法

ES模組化的匯入和匯出 ES模組化的匯入和匯出

import

1、接下來我們想在 b.js這個檔案用到上述所有的變數,這時我們可以使用 import進行匯入,於是乎如下

b.js

import values from './a.js'
console.log(values);

在 node.js 中我們常常將 a.js 通過 const values = require('./a.js')將a.js的變數 一股腦的全部匯入到 values 這個變數中

所以面對 import 我們很自然的就想這麼用,但是意外就發生了,如果如上述所寫,就會出現下面的錯誤

image-20210206132008886

說是啥沒有提供一個預設匯出的變數,這個先放著,後面再講

2、正確寫法如下

b.js

import {num1, height, flag, sum, add, Person} from './a.js'

console.log(num1)
console.log(height)
console.log(flag)
console.log(sum)
console.log(add(1, 3))
console.log(new Person('小明', 20))
new Person('小明', 20).show()

輸出結果如下

image-20210206132505586

這裡可以發現,我們要想使用 a.js 檔案中的某個變數必須要用 {}括起來,這就和之前面批量匯出用 export {}的花括號,括住想要匯出的變數相對應了

import * as

之前面我們通過 import {} from 將想要匯出的變數全部寫在花括號裡,但是若裡面的變數太多,又全部都需要使用,那麼這種寫法可真要累死人

所幸有個更方便的寫法,如下所示,我們可以將 a.js 中的所有檔案全部匯入到 values 變數中,然後用 values.xx的方式呼叫

b.js

import * as values from './a.js'

console.log(values.num1)
console.log(values.height)
console.log(values.flag)
console.log(values.sum)
console.log(values.add(1, 3))
console.log(new values.Person('小明', 20))
new values.Person('小明', 20).show()

輸出結果也沒有任何變化,和上面的一樣

export default

1、之前我們首次使用 import,想用匯入全部變數時出現瞭如下錯誤

import values from './a.js'

image-20210206132008886

2、現在我們就應該能懂的為什麼會報錯,並且 export default 是什麼意思了,我們先在 a.js 加上一行

a.js

export default function mul(x, y){
  return x * y
}

3、然後再在 b.js 檔案中引入

b.js

import values from './a.js'

console.log(values(2, 10))

輸出結果

image-20210206135342358

所以 export default 的作用就是匯出一個預設變數,這個預設變數就是扛把子,之後我們使用 import xx from aa 的時候就會將 aa 中的預設變數賦到 xx 上面,而無需使用 import { xx } from aa 了

注意

1、如果我們按照之前花括號的方式進行匯入

import {mul} from './a.js'

console.log(values(2, 10))

會報這樣的錯誤

image-20210206135546524

2、經過測試,有如下三種方法可以匯入 export default 預設暴露出的變數

import values from './a.js'
import {default as m} from './a.js'
import * as val from './a.js'

console.log(values(2, 10))
console.log(m(3, 10))
console.log(val.default(4, 10))

輸出結果

image-20210206135726807

import 和 require 的區別

最後再來說一下 import 和 require 的區別

  1. 出現的時間、地點不同
年份 出處
require/exports 2009 CommonJS
import/export 2015 ECMAScript2015(ES6)
  1. 不同端(客戶端/伺服器)的使用限制
require/exports import/export
Node.js 所有版本 Node 9.0+(啟動需加上 flag --experimental-modules) Node 13.2+(直接啟動)
Chrome 不支援 61+
Firefox 不支援 60+
Safari 不支援 10.1+
Edge 不支援 16+
  • 原生瀏覽器不支援 require/exports,可使用支援 CommonJS 模組規範的 Browsersify、webpack 等打包工具,它們會將 require/exports 轉換成能在瀏覽器使用的程式碼。
  • import/export 在瀏覽器中無法直接使用,我們需要在引入模組的 script 元素上新增type="module屬性。
  1. require/exports 是執行時動態載入,import/export 是靜態編譯

參考

https://zhuanlan.zhihu.com/p/121770261

https://www.bilibili.com/video/BV15741177Eh?p=74

https://www.bilibili.com/video/BV15741177Eh?p=75

相關文章