Import和require的區別不用多說了,分屬於不同的規範,我們今天分別來試試怎麼使用它們
Common.js
該規範通過exports
和module.exports
進行導出,通過require
進行導入,我們看下面兩個簡單的例子:
// b.js
module.exports = {
bb: 'hello bbb'
}
// c.js
exports.cc = 'hello ccc'
// index.js
var bb = require('./b.js')
var cc = require('./c.js')
console.log(bb) // { bb: 'hello bbb' }
console.log(cc) // { cc: 'hello ccc' }
既然exports
和module.exports
都可以導出,那麼它倆什麼區別呢,其實node爲每個模塊提供一個exports變量,指向module.exports,即:exports.name
和module.exports.name
一樣的,但是他倆其實也有細微差別,我們後面會講到。exports
和module.exports
的差別我先總結一下,後面再通過例子驗證:
exports
可以重複使用,導出多個對象module.exports
重複使用時,以最後一個module.exports
爲準exports
和module.exports
一起使用時,exports
的對象都無法導出
我們一個一個來驗證:
/* exports可以重複使用,導出多個對象 */
// c.js
exports.aa = 'hello aa'
exports.bb = 'hello bb'
exports.cc = 'hello cc'
// index.js
var cc = require('./c.js')
console.log(cc) // { aa: 'hello aa', bb: 'hello bb', cc: 'hello cc' }
/* module.exports重複使用時,以最後一個module.exports爲準 */
// c.js
module.exports = {
aa: 'hello aaa'
}
module.exports = {
bb: 'hello bbb'
}
// index.js
var cc = require('./c.js')
console.log(cc) // { bb: 'hello bbb' }
/* exports和module.exports一起使用時,exports的對象都無法導出 */
// c.js
exports.aa = 'hello aaa'
module.exports = {
bb: 'hello bbb'
}
exports.cc = 'hello ccc'
// index.js
var cc = require('./c.js')
console.log(cc) // { bb: 'hello bbb' }
我剛剛說過exports.name
和module.exports.name
一樣的,但是他倆其實也有細微差別,我們先說說他倆一樣的地方:
// c.js
exports.aa = 'hello aaa'
module.exports.bb = 'hello bbb'
exports.cc = 'hello ccc'
module.exports.dd = 'hello ddd'
// index.js
var cc = require('./c.js')
console.log(cc) // { aa: 'hello aaa', bb: 'hello bbb', cc: 'hello ccc', dd: 'hello ddd' }
爲了看它倆的差別,我們在中間插入一個module.exports
看看:
// c.js
exports.aa = 'hello aaa'
module.exports.bb = 'hello bbb'
module.exports = {
main: 'hello main'
}
exports.cc = 'hello ccc'
module.exports.dd = 'hello ddd'
// index.js
var cc = require('./c.js')
console.log(cc) // { main: 'hello main', dd: 'hello ddd' }
可見,三種寫法都使用的時候,只有module.exports
和處於module.exports
下方的module.exports.dd
指向的對象可以導出
ES6
es6使用export
導出,使用import
導入,我們先舉幾個簡單的例子:
// a.js
export var aa = 110
export const bb = 'hello bb'
var cc = 2
export {
cc
}
// index.js
import * as all from './a.mjs'
console.log(all) // [Module] { aa: 110, bb: 'hello bb', cc: 2 }
注意,export的實質是暴露接口,在接口名與模塊內部變量之間,建立一個一一對應的關係,所以以下的寫法是有問題的:
// 以下寫法均會報錯
var kkm = 1
export kkm
export 'hello'
export {
kk: 'hello'
}
有一種情況也會報錯:
// 不報錯
var cc = 2
export {
cc
}
// 報錯
var cc = 2
export {
cc: cc
}
as關鍵字
as關鍵字相當於給導出和導入的接口名起的別名,export
和import
均可以使用
// b.js
const bb = 'hello bb'
export {bb as bbInter}
// index.js
import * as all from './b.js'
console.log(all) // { bbInter: 'hello bb' }
// b.js
const bb = 'hello bb'
export {bb as bbInter}
// index.js
import {bbInter as bb} from './b.js'
console.log(bb) // hello bb
default關鍵字
defalut
其實是一種簡寫的寫法,相當於將模塊中一個名爲default的變量作爲接口暴露出去,舉例子:
export default 54;
// 等價於
var dind = 54;
export {dind as default};
因此,default只能export一次,如果多次export,則會報錯
Duplicate export of 'default'
export default
對應的import寫法:
import bb from './b.js'
// 等價於
import {default as bb} from './b.js'
和commonJs規範不同,export
暴露的是接口,可以認爲是指針,即export
的變量發生變化時,import
的變量也會發生變化,我們來測試一下:
// b.js
var dind = 54;
// 變化
setTimeout(() => {
dind = 'change'
}, 2000)
export {dind as default};
//index.js
import bb from './b.js'
setInterval(() => {
console.log(bb)
}, 500);
index.js
運行結果:
54
54
54
change
change
change
...