糟糕的默认导出(export default)

169 阅读3分钟

前言

JavaScript 模块有两种定义导出的方法:默认导出命名导出。默认导出export default,大家非常常见,我想解释为什么默认导出是一种糟糕的做法并导致更糟糕的开发人员体验,本文将从几个方面来总结,将他糟糕的一面展示给你。

导出方式

export const add = (a, b) => a + b;

export default (a, b) => a - b;

既有默认导出又有命名导出

在考虑如何导入和使用它之前,有一个影响开发人员体验的问题。那就是:为什么 subtract 是默认导出,而 add 是命名导出?

考虑到使用他们的是不熟悉的开发人员,或者是复杂模块。他们可能不知道哪个导出是默认的甚至可能不知道有默认导出。这导致开发人员需要花更多时间阅读文档(假设甚至有任何文档)或阅读库源代码。如果只有命名导出,那么发现就变得简单了。

使用 IDE,我们可以立即看到模块的导出成员。那么这个列表中缺少什么?没错,默认导出。因此,IDE 无法以有意义的方式在此列表中显示它。

VS Code Intellisense

事实上,这让我想起了 Node 对模块格式——CommonJS 的失败尝试——极其糟糕的开发者体验。判断代码是否使用 CommonJS 的一种简单方法是看到 require 和 module.exports 。与默认导出非常相似,几乎没有 IDE 帮助。

现在我已经绕过 IDE 工具(并发现了自动完成方面缺少名称的问题),一旦您弄清楚了如何导入它们,我现在将扩展默认导出的用法。

  • 可以使用 任意名称 导入导出的成员。没错,subtraction函数可以用任何名称导入,包括 multiply 。但是这将导致混乱,尤其是随着代码库的增长。

    import multiply from './math.js';
    const result = multiply(2, 2);  // 结果是0
    
  • 由于可以使用任何名称导出默认导出,多个开发人员可能会为默认导入想出不同的名称和命名方案。不会有一致性!众所周知,起名字是前端最痛苦的一件事情

  • 默认导出也是重构时痛苦的存在。如果我重命名模块中的命名导出成员,那么任何用法也将被重命名(前提是您使用的是可以应用此重构的 IDE)。使用默认导出,这是不可能的。

您可能会想,“如果来自不同模块的两个命名导出具有相同的名称,我该怎么办?”。幸运的是,这个问题很容易用 import aliasing 解决。

import { Article } from './types';
import { Article as ArticleComponent } from 'my-design-system';

当然,虽然您仍然需要为别名起一个名称,但比完全为默认导出发明一个名称要好得多。这仍然是重构友好的。 ArticleComponent 是一个多余的名称,尤其是在使用从设计系统组件库导入的组件时。

但正如俗话说命名事物很难。但是,我更乐于处理范围限定为单个文件的一次性名称,而不是没有名称,然后每次导入时都想一个名称。

您可能还会想,“我使用的框架或工具几乎要求我默认导出功能或组件”。您也可以使用“index.js 模式”来解决这个问题。这是您在目录根目录中创建 index.js 或 index.ts 文件的位置,然后从那里导出默认导出。可以在此处参考文章

如果您正在编写模块,无论是严格用于您的代码库/项目还是 NPM,请停止编写默认导出

全文完。

谢谢!