浅析javascript中的export/import 与commonjs的require/exports,以及export default的问题

news/2024/7/19 14:57:10 标签: javascript, js, commonjs

我想先解释一下commonjs(cjs)的导出导入概念,结合他来理解es6 module(esm)更好理解。

在commonjs,大部分情况就是nodejs中,定义导出的时候其实就是exports对象,比如

javascript">module.exports = {a: 1, b: 2};
// 或者
module.exports.a = 1;
module.exports.b = 2;

以上,其实module.exports本身是一个Object,他作为commonjs规范下模块的默认(default)导出,这里可以理解为相当于ES6的export default

但值得注意的是,commonjs中仅仅支持这一种默认导出。不支持类似于ES6中:

javascript">export const a = 1;
export const b = 2;

以上是具名导出(named export), 也就是说如果你想使用’具名导入’的方式去导入一个commonjs的包,是会报错的。因为cjs根本就不支持。

javascript">// module1.cjs
module.exports = {a:1};

// module2.mjs
// const {a} = require('./module1') // 可以执行,因为前边是解构语法
import {a} from './module1.cjs' // 不可以执行,因为这个named import,不是解构。

上述代码执行报错如下:

SyntaxError: Named export 'a' not found. The requested module './module1.cjs' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from './module1.cjs';
const {a} = pkg;

这个报错非常的人性化,清楚的解释了你有一个语法错误,也就是import {a} from './module1.cjs'这种导入会去被导入的包中寻找具名的导出,就是export const a = 1这种导出。但cjs是不支持的,所以报错了。

到这里,我想简单总结下,在模块导入导出的过程中,对于cjs和esm,他们支持两组导出:

  • module.exports / export defalut对应着 require() / import anyName from './'
  • 具名导入导出(named export) export const a; export const b 对应着 import {a, b} from './'

网上有文章说,最好不要使用export default,究其原因是因为这个会引起歧义,比如以下这种场景:

javascript">//module1.js
export default {a: 1, b: 2};

// module2.js
import {a, b} from './a'

上述代码是错误的。因为module2中的语法不是解构,而是去寻找module1中的具名导出。而实际上module1中是没有的。所以会报出undefined。

实际上他是以下语法的简写

import {a as a, b as b} from './module.mjs'

不是下面的简写

import {a: a, b: b} from './module.mjs'

如果你真的想去解构,应该这样写:

javascript">import module1 from './module.mjs'
const {a, b} = module1;

所以倒不是不让用export default,而是需要注意到潜在的问题。

最后,在模块导出的时候,你可以写一种兼容的写法,也就对于导入者来说,他怎么导入都不会错。

const api = {a, b}
// 有默认导出
export default api;
// 也有具名导出
export const {a, b} = api;

http://www.niftyadmin.cn/n/1382925.html

相关文章

易维帮助台:企业售后服务如何高效派单

企业在做售后服务时,客服部门人员成为处理事件的开头者,需要把客户问题转给其他部门。如何实现高效派单成为企业在售后服务上理所应当该重视的问题。其实,随着市场的拓展,市面上利用工单系统来解决派单的工作流程,并应用在各个行业中,成为最广泛的一种服务方式,帮助企业在做售后…

在WPF下快速生成线的方法

原文:在WPF下快速生成线的方法如果线较多时,在画布中用Path或Line生成时会比较慢。用DrawingVisual可以快速生成,这个在之前我的博客中已经提到。但在类库形式下生成的无法看到,保存成Image后再加入图层后成功显示。 DrawingVisual drawingVi…

使用eggjs + axios post方式通过blob对象进行文件下载

以下是egg.js的后台代码 const Controller require(egg).Controller; const path require(path); const fs require(fs);class HomeController extends Controller {async index() {const filePath path.resolve(this.app.config.static.dir, file_message_to.png);this.c…

caffe+Ubuntu14.04.10 +cuda7.0/7.5+CuDNNv4 安装

特别说明: Caffe 官网地址:http://caffe.berkeleyvision.org/本文为作者亲自实验完成,但仅限用于学术交流使用,使用本指南造成的任何不良后果由使用者自行承担,与本文作者无关,谢谢!为保证及时更…

金庸笔下的良好代码风格(转)

原文url:http://news.cnblogs.com/n/202531/ 我零九年看过一本小说,讲程序员的故事,从此,了解了一个新物种。最近又看《红楼梦》,史湘云有条谜语:“溪壑分离,红尘游戏,真何趣&#x…

Microsoft Edge市场占有率远落后于Google Chrome

微软Edge是Windows 10的默认浏览器,随着Windows 10操作系统的普及,普遍认为Edge也将获得用户的青睐。但是根据数据显示,这种情况并未发生。2016年6月,Edge仅仅能够维持它的用户量,这距离它的竞争对手Firefox和Google C…

实际中使用Javascript中sessionStorage的注意事项

平常时候使用sessionStorage,只是相当于把他当做临时的缓存,当用户在页面间跳转的时候可以共享数据。 但如果细细分析,sessionStorage还是有一些注意事项的。了解这些,可以避免在项目中出现莫名其妙的问题。 首先引用一段MDN的解…

Makefile之 =, :=, ?=

转自: Makefile之 , :, ? Makefile: A "World" all: echo $(A) Makefile: A $B "World" B "Hello" all: echo $(A) ###--------------- 用“”定义变量的时候,右边如果有变量,则…