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
...