CommonJs
导出方式
1. module.exports = 变量/函数
这种方式导出的是变量/函数。使用时引入可以直接调用
例如:
// test.js
const test = () => {console.log(‘111’)}
module.exports = test
// usage
const test = require(‘./test.js’)
test()
2. module.exports.test = 变量/函数
这种方式导出的是一个对象,其中test是导出对象的一个属性
例如:
// test.js
module.exports.test = () => {console.log(‘111’)}
// usage
const test = require(‘./test.js’)
test.test()
3. 混合模式,1、2种混合
这种情况调用方式也是区分开来的,例如:
// test.js
const testA = () => {console.log(‘111’)}
module.exports = testA
module.exports.testB = () => {console.log(‘222’)}
// usage
const test = require(‘./test.js’)
test() // 第一种导出函数的调用方式
test.testB() // 第二种导出函数的调用方式
ES6 module
import 在导入的时候两个组成部分分别是:要导入的标识符和标识符应该从哪个模块导入
特别注意:直接使用导入标识符时,要保证导入的标识符应该和导出的标识符保持一致。
// model.js
let a = 1, b = 2
export {a, b}
export let c = 2
// usage
import {a, b, c} from ‘model’
import {a as A, b as B, c as C} from ‘model’
默认导出、导入
// export
export default 1
// import
import defaultExport from ‘model’
混合导出
// model.js
let a = 1
export { a }
const b = 2
export { b }
export let c = 3
export default [1,2,3]// 这个是完全可以的,不管是ESM还是CMD,导出语句只是一句声明对外的接口的语句
// 混合导入
import defaultExport,{a,b,c as newC} from 'model' // defaultExport:[1,2,3] a:1 b:2 newC:3
import defaultExport, * as name from 'model' // defaultExport:[1,2,3] name:{a:1,b:2,c:3}
import * as name from 'model' // name:{a:1,b:2,c:3,default:[1,2,3]}
在混合导出的时候,有2个规则:
- 在混合导出时,export default导出的,在导入时必须放在最前面,否则会报错
- 在导出的时候,export default 一个模块当中只允许导出一次。
ESM export
导出的时候必须是命名式导出,必须有变量/函数/类来承载对外的接口
// 错误
export 1
var a =1
export a
第二种方法错误的原因是因为最后还是导出的是数值1,而不是变量1
可以这样改
// 正确
var m = 1
export { m }
或者
var m = 1
export { n as m }
因为后面两者都导出了是一个对象
`// 正确`
`export var a = 1`
同理,在导出function的时候
// 报错
function f () {}
export f
//正确
export function f () {}
// 正确
function f () {}
export { f }
ESM当中的默认导出和声明导出的区别?
1. 首先体现在引入的方式上
默认导出
// export default导出方式
let name = 'jack'
export default function ss() {
console.log(name)
}
在引入时刻,相当于引入了匿名函数
import s1 from './test.mjs'
同时也说明了在导出的是匿名函数,不需要导出和导入的一一对应
声明导出
let name = 'jack'
export function ss() {
console.log(name)
}
import ss from './test.mjs'
上述导出方式就会直接报错
The requested module './test.mjs' does not provide an export named 'default'
因为直接使用这样的导入方式会被认为是引入一个默认的导出模块,但是没找到默认的导出模块,肯定会报错
// 正确
import {ss} from './test.mjs'
2. 其次体现在导出两者的意义上
本质上export default是导出的一个default的变量或者方法,所以在引入的时候,可以任意的命名。
export是“标准”的输入格式,对应的import肯定也只能用“标准”的导入
demo3当中直接赋值一个function的声明可以
//demo3
export default function name() {}
// export default的本质是讲后面的值赋值给default,因此demo4当中的这样的直接给值的方法也是可以的
// demo4
export default 42
//这样相当于把 42赋值给了default变量
module.exports和exports的区别是什么?
- module.exports初始值是一个空对象
- exports指向的是module.exports的引用
- require()返回的是module.exports而不是exports
开始的时候系统自动给node增加了两个对象分别是exports 和module。
model有一个exports属性默认指向{},即exports也指向{} .
示意图: exports =>{} <= module.exports 。 如果其中一个被赋值之后,即指向了另外的内存块,那么两者就没有关系.
//foo.js
exports.a = function(){
console.log('a')
}
module.exports = {a: 2}
exports.a = 1
var x = require('./foo');
console.log(x.a) //2
通过这个就可以看出exports是引用的module.exports的值,module.exports改变的时候exports不会被改变,而模块导出的时候执行的是module.exports而非exports
因为exports和module.exports默认是指向的同一块内存,但是是可以通过来重新给exports赋值,改变exports的指向
// 正确
exports.a = function() {}
module.exports.a = function() {}
// 错误
exports var a = 1 (1)
exports = function() {} (2)
(1)是因为语法问题而出错
(2)是因为导出的时候相当于exports指向了另一块内存,已经不再指向module.exports
经过上述例子可以总结出一个非常容易的结论即:exports只能在自己身上挂属性,而不是给自己重新赋值。
exports 挂上属性之后得到的比如exports.a 实际上等价于 module.exports.a
能导出来是一方面但是主要问题在于require只认module.exports,因此才有上面的结论。
评论区