侧边栏壁纸
博主头像
warlock博主等级

夏响青篁冬悦雪, 昼巡红镜夜观天

  • 累计撰写 11 篇文章
  • 累计创建 6 个标签
  • 累计收到 0 条评论
标签搜索

目 录CONTENT

文章目录

commonJs, ES6 and ESM export

warlock
2022-08-23 / 0 评论 / 0 点赞 / 601 阅读 / 1,444 字

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个规则:

  1. 在混合导出时,export default导出的,在导入时必须放在最前面,否则会报错
  2. 在导出的时候,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的区别是什么?

  1. module.exports初始值是一个空对象
  2. exports指向的是module.exports的引用
  3. 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,因此才有上面的结论。

0

评论区