为什么 JavaScript 有默认导出?

Dav*_*nan 5 javascript es6-modules

语境

JavaScript 有两种类型的导出:正常[1]和默认。

编辑:JavaScript 有两种类型的导出语法

正常出口

class Foo {...}
class Bar {...}

export {
  Foo,
  Bar,
};
Run Code Online (Sandbox Code Playgroud)

或者

export class Foo {...}
export class Bar {...}
Run Code Online (Sandbox Code Playgroud)

普通导出可以通过两种方式导入:命名空间[1]导入和命名导入(看起来类似于解构)。

命名空间导入

import * as Baz from './baz';
Run Code Online (Sandbox Code Playgroud)

命名导入

import {Foo, Bar} from './baz';
Run Code Online (Sandbox Code Playgroud)

默认导出

class Foo {...}
class Bar {...}

export default {
  Foo,
  Bar,
};
Run Code Online (Sandbox Code Playgroud)

默认导出也可以通过两种方式导入:名称空间导入和命名导入(以一种黑客方式在单独的语句中使用解构)

命名空间导入

import Baz from './baz';
Run Code Online (Sandbox Code Playgroud)

命名导入

import temp_Baz from './baz';
const {Foo, Bar} = temp_Baz;
Run Code Online (Sandbox Code Playgroud)

问题

普通导出和默认导出都具有相同的功能 - 它们可以导入到命名空间中,并且可以解构为更小的部分。

1) JavaScript 具有默认导出而不是坚持使用普通导出并让导入语法如下的原因是什么?

import <varName> from <location>;
Run Code Online (Sandbox Code Playgroud)

<varName>将允许像任何变量赋值一样进行解构,而无需特殊的“命名”导入。

Node.js 在没有默认导出的情况下进行管理,唯一的额外更改是允许导出单个值:

module.exports = class Foo {...}
Run Code Online (Sandbox Code Playgroud)

export =这可以用或类似的东西来完成export only:

export only class Foo {...}
Run Code Online (Sandbox Code Playgroud)

export only现在您可能会问,和 之间有什么区别export default?

  • export only导出可以使用相同的语法导入,而export default需要不同的导入语法。为了允许两种语法都适用于模块用户,模块必须具有export相同export default的项目(这是我在所有模块中所做的事情)。
  • export default被重命名为export only我认为更好的术语(不那么混乱;更清晰)

2) 上面列出的所有差异都是优点。还有其他缺点吗?或者上述任何差异也可能是缺点吗?


编辑

看来我误解了 的预期用途export default。

它用于在常规导出之上添加默认导出。

所以我现在想知道什么时候使用默认导出?尽管我可能不应该对这个问题添加更多内容。

如果默认导出的唯一用途是您的模块只有一个要导出的项目,那么这个问题仍然适用。

编辑2

现在看来,预期用途是模块仅导出单个项目。所以我的问题仍然适用。为什么不将默认导出替换为export only,从而不再需要额外的默认导入语法?


笔记

[1]我不确定这是否是正确的术语

jam*_*her 9

“默认导出”和“命名导出”的存在是由于委员会的设计。安德烈亚斯·罗斯伯格在最初的设计讨论中令人信服地论证了这一点:

有些人想要传统意义上的模块,作为带有命名导出的封装名称空间,您可以导入和访问合格或不合格的模块,以及检查导入的位置。

有些人想要 ES6 之前的特定 JavaScript 风格的模块,它们可以是任意 JS 值,并且按照良好的旧 JavaScript 传统,检查并不重要。

当前的设计(包括最新的导入建议)似乎没有让任何一方满意,因为它试图在语义上成为前者,但在语法上希望针对后者进行优化。主要结果是混乱。

也就是说,“默认导出”的动机不是技术性的,而是政治性的,旨在安抚 CommonJS 和 AMD 世界中的人们,在这些世界中,模块导出单个值。这巧妙地解释了为什么我们将两个模块系统合而为一;这是我们在其他编程语言中看不到的东西。

(非常感谢 Bergi,他在答案中发现并引用了该线程。但是,我不同意他的结论,即默认导出是出于对速记的需要。我在原始线程中没有看到对此进行太多讨论。 )


Tob*_*biq 0

export default {
  Foo,
  Bar,
}
Run Code Online (Sandbox Code Playgroud)

我不明白你为什么要演示这个结构。这不是它应该如何使用的。

默认导出实际上只是另一种导出。如果您import * as Package from "package"会意识到...Package.default是默认导出

唯一的变化是语法快捷方式:

import alias from "package"=import {default as alias} from "package"

它使许多包的使用变得更容易/更简单。


export = ...不等于export default ...

前者返回一个模块结构,...后者返回一个模块结构{default: ...}