es6模块化导入导出与commonjs模块化(nodejs导入导出)详解——导出export

本文详细比较了前端开发中ES6模块化与CommonJS模块化的导入导出差异,以作者在使用Nest.js框架时遇到的时区插件问题为背景,介绍了如何处理commonjs插件的导入错误,并提供了基础导出和导入语法的实例。
摘要由CSDN通过智能技术生成

博主的桌面工具软件已经正式开发,获取方式:

  • 可以关注我的小程序【中二少年工具箱】获取。(若小程序更新有延迟,或关注小程序后续功能,可先收藏小程序)

  • 通过下载链接

  • 百度网盘:
    链接:https://pan.baidu.com/s/15zDnSoEzJGSZLjpD2FYrMw?pwd=1234 提取码:1234 复制这段内容后打开百度网盘手机App,操作更方便哦

具体已实现功能,参考文章中二少年工具箱简介



前言

本文主要解释前端两种模块化语法:es6模块化与commonjs模块化,纯前端一般遵循es6模块化,使用import语法导入插件,nodejs遵循commonjs模块化,使用require导入插件。

本文虽长,但读完后,正常情况下,足以应付大部分导入导出场景,使用其他人插件再也不用因为导入导出的语法耗费时间。


一、起因

我的小程序后端采用midwayjs框架(nestjs也不错,个人项目支持一波国产),后端部署到腾讯云上,考虑到个人项目服务器有很大概率会迁移,下一个服务器什么情况不好预估,开发某些功能时就需要考虑时区问题,所以使用插件moment-timezone。

使用插件时,遇到报错,信息如下:Module ‘“F:/myProject/lize-tools-back/node_modules/moment-timezone/index”’ can only be default-imported using the ‘esModuleInterop’ flag

造成这报错的起因是我在导入插件时,使用了es6的默认导入方法,而moment-timezone插件遵循commonjs模块化。插件的源码就不贴了,因为它用了ts导出单个对象的方式,这部分知识点和我们本章要了解的并不想关,我们只需要知道,插件最终会被编译成

module.exports = moment

这是明显的commonjs导出方法。

而我如果使用es6默认导入方法:

import moment from 'moment-timezone'

就会报上面的错。

这错误并不是es6或者nodejs抛出的,因为从Node.js v13.2 版本开始,Node.js 已经默认打开了 ES6 模块支持(这句话抄的阮一峰大神,我没有自己考证)。

上面的错误其实是ts提示的,ts认为commonjs中没有默认导出的概念,默认导出是es6中的概念,所以自然也不能用import默认导入的方式。按照提示配置esModuleInterop,我们可以绕过报错,但是从这个报错,我正好整理了一下es6模块化和commonjs模块化(nodejs)导入导出的概念,希望对其他人有所帮助。

二、两者基础对比

对于两种模块化的基础使用方式容易混淆,无非是没有认认真真地对比过它们,大家不愿意做,我来为大家节省时间:

导出语法导入语法
commonjs模块化1. module.exports=xxx 2.exports.变量名=xxxconst xxx=require()
es6模块化1.export default xxx 2. export xxx1.import {xxx} from 2.import xxx from 3.import * as xxx from

其中xxx可以是函数、变量、类等任意对象。

三、commonjs导出

简单举例:

module.exports={
	test:'1'
}

exports.test=1

当然实际情况可能还有很多变种语法,但是初学者只需理解这两个最根本的即可。

学知识就和练葵花宝典一样,要学最紧要的心法,切了最重要,至于用针还是用剑,那就是变招,终会根据喜好水到渠成。

上面两个导出的效果一样,最终都是会得到一个对象exports,exports对象里有个key是“test”,对应的value是1。

两种写法无非就是一个明确告诉你exports对象是module的一个元素,另一个简洁化,没有告诉你exports前面其实还有个module。

就像前端写全局变量,直接写a=1和写window.a=1,有区别吗?没区别!

当然这是为了方便大家记忆,实际上exports是一个指向module.exports的引用,这样说有点过于拗口,用代码描述,就是底层代码通过exports===module.exports创建了exports。

所以我们使用exports时,千万要写成exports.test=1的形式,如果写成exports=1,那么exports和module.exports之间的关系很可能就被你强行断开,导致出错。(当然我没这么二去试过)

四、es6导出

我为什么在介绍commonjs导出后,不接着介绍commonjs对应的导入?因为能看这篇文章的,我相信一定是对导入导出语法有一点了解,但又不多,大家会对commonjs导入和导出混淆吗?不会,大家更容易混淆的是commonjs的导出与es6的导出。

简单例子:

export default function test(){
}
export default class{

}
export default 1

export const test=function(){}
export const test=class{
}
export const test=1

其实对照着看commonjs和es6导出,很容易分辨出来。它俩唯一容易混淆的地方就是都有export这几个字母而已,但是两者的export单词代表的含义却完全不同。

commonjs中的是exports,它是一个对象,是要导出去的对象,所以带着s很好理解,因为这个对象可能有很多属性。

es6中的是export,它是一个关键字,是类似于function 、class这种具有一定功能性的方法,它又不是单纯的对象。不要杠前端一切皆对象,我相信能杠这种话的人一定知道我说的单纯对象是什么意思。

聊到这就很清晰了,commonjs中导出的就是这个exports对象,es6中导出的是export后面的对象。至于细节,两者的对象都可以是什么,构造这个对象有没有更多的方式,能不能重命名等等等等,自己去看看文档就知道了,我不建议死记硬背。

理解了基础,其他的用的多了自然就知道了,用的不多,说明不那么重要。

再简单聊下es6导出的两种形式,我们只需要理解export default中的default才是要导出去的变量,把它后面的对象赋值给default,然后导出,就是默认导出方式。所以default后面一定是一个对象或对象的引用,而不是声明语句。

如果写成export default const test=1,这就直接给es6干懵圈了,它不知道该导出default还是导出test。但如果写成:

const test=1
export default test

就是可以的,因为导出的还是default,只不过把变量a的值赋值给default了。就是说你可以写let a=b=c=3,但你不能写let a=let b=let c=3。

同理,export 1也不行,因为export是关键字,它要导出一个变量,1不是变量,但是export test就可以,因为test是我们声明的一个变量,不论它是在export这句话里声明的,还是在之前声明的。

这里,我建议不要使用export default默认导出方式,我有很长一段时间就只用export const test=1这一种写法,覆盖百分之九十九的业务场景。export default个人理解其实更多是插件、基础组件等需要考虑的。进阶内容就不展开说了,这是另外的价钱。

五、总结

本来打算一篇文章写完的,结果发现不管怎么压缩,都需要很长的篇幅,还是把导入导出分开阐述吧。感觉读完本文有所收获,请搜索博主下一篇关于导入import的讲解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

中二少年学编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值