環境準備
三個檔案 1.html
、a.js
和 b.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)
這是三個特別特別簡單的程式碼,然後我們讓他們在伺服器上執行,為了方便我就使用 vscode
的 Live Server
外掛執行程式碼
執行結果
開啟控制檯後,會發現輸出一行 false
模組化
由此可以看出,在js檔案中定義的變數已經汙染了全域性,隨著專案的增大這可能會導致不必要的麻煩
於是我們需要進行如下操作
<script src="a.js" type="module"></script>
<script src="b.js" type="module"></script>
當在 script 標籤上加上 type="module"
就代表這個檔案是一個模組,之中定義的屬性在全域性就訪問不到了。
然後我們再看控制檯,就會發現如下的錯誤
這就表明我們在 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
}
他會報下面的錯誤,並且連編譯器也會認為這個寫法不合法
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
我們很自然的就想這麼用,但是意外就發生了,如果如上述所寫,就會出現下面的錯誤
說是啥沒有提供一個預設匯出的變數,這個先放著,後面再講
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()
輸出結果如下
這裡可以發現,我們要想使用 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'
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))
輸出結果
所以 export default 的作用就是匯出一個預設變數,這個預設變數就是扛把子,之後我們使用 import xx from aa 的時候就會將 aa 中的預設變數賦到 xx 上面,而無需使用 import { xx } from aa 了
注意
1、如果我們按照之前花括號的方式進行匯入
import {mul} from './a.js'
console.log(values(2, 10))
會報這樣的錯誤
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))
輸出結果
import 和 require 的區別
最後再來說一下 import 和 require 的區別
- 出現的時間、地點不同
年份 | 出處 | |
---|---|---|
require/exports | 2009 | CommonJS |
import/export | 2015 | ECMAScript2015(ES6) |
- 不同端(客戶端/伺服器)的使用限制
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屬性。
- require/exports 是執行時動態載入,import/export 是靜態編譯
參考
https://zhuanlan.zhihu.com/p/121770261