環境准備
三個文件 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