为什么JavaScript具有默认导出功能?

时间:2019-07-13 16:02:03

标签: javascript es6-modules

上下文

JavaScript有两种导出类型:普通 [1] 和默认。

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

正常出口

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

export {
  Foo,
  Bar,
};

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

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

命名空间导入

import * as Baz from './baz';

命名进口

import {Foo, Bar} from './baz';

默认导出

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

export default {
  Foo,
  Bar,
};

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

命名空间导入

import Baz from './baz';

命名进口

import temp_Baz from './baz';
const {Foo, Bar} = temp_Baz;

问题

常规导出和默认导出都具有相同的功能-它们可以导入到名称空间中,也可以分解为较小的片段。

1)JavaScript具有默认导出功能而不是仅坚持常规导出并具有以下导入语法的原因是什么?

import <varName> from <location>;

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

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

module.exports = class Foo {...}

这可以通过export =export only或类似方法完成:

export only class Foo {...}

所以现在您可能会问,export onlyexport default有什么区别?

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

2)上面列出的所有区别都是优点。缺点还有其他区别吗?还是上述任何区别也是不利的?


编辑

似乎我误解了export default预期用途。

用于在常规出口的基础上添加默认出口。

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

如果默认导出的唯一用途是模块仅导出单个项目,则此问题仍然适用。

编辑2

现在,如果模块仅导出单个项目,则看来的用途是。所以我的问题仍然适用。为什么不用export only替换默认导出,而无需其他默认导入语法?


注释

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

3 个答案:

答案 0 :(得分:1)

  

JavaScript有两种导出类型:普通和默认。

不,不是。 JavaScript只有一种导出结构。但是它具有不同的语法。

export default function x() {}只是function x(){} export { x as default }的简写。
import x from '…'只是import { default as x } from '…'的简写。

您讨论的两个模块导出之间的差异远大于单个default关键字。它们看起来如此相似,因为您使用了速记符号。完全说明了,是

export {
  Foo as Foo,
  Bar as Bar,
} // a declaration

vs

export default ({
  Foo: Foo,
  Bar: Bar,
}); // an object literal
  

常规导出和默认导出都具有相同的功能-它们可以导入到名称空间中,也可以分解为较小的片段。

不,他们没有。导入为导出的变量声明提供别名,没有解构-和you cannot do that to properties of a default-exported object

  

JavaScript具有默认导出功能而不是仅坚持常规导出并具有以下导入语法的原因是什么?

请参见https://esdiscuss.org/topic/moduleimport。 default-export语法提供了以特殊名称default进行导出的简写语法(否则,该名称不是有效的变量名),因为从模块中仅导出单个内容是一种很常见的用例。无论如何,当此模块中只有一个值时,不需要显式命名值。在这方面,它非常符合您为export only的建议所设想的目的,但是它只是一个导出,没有提供多个可别名导出的完整命名空间。

答案 1 :(得分:1)

“默认出口”和“命名出口”的存在是由于委员会的设计。这是convincingly argued by Andreas Rossberg during the original design discussions

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

有些人希望使用ES6之前的JavaScript特定样式的模块,这些模块可以是任意JS值,并且遵循古老的JavaScript传统,即检查无关紧要。

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

也就是说,“默认出口”的动机不是技术上的,而是政治上的,其目的是安抚CommonJS和AMD领域中的模块出口单一值的情况。这很好地解释了为什么我们将两个模块系统合二为一。我们在其他编程语言中看不到的东西。

(非常感谢Bergi,他在his answer中找到并引用了该线程。但是,我不同意他的结论,即默认出口是由速记的驱动所得出的结论。这在原始线程中。)

答案 2 :(得分:0)

export default {
  Foo,
  Bar,
}

我不明白您为什么演示了这种结构。这不是应该使用的方式。

默认导出确实是另一个导出。如果您import * as Package from "package"将会意识到... Package.default是默认导出

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

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

它使使用许多包装更加容易/简单。


export = ...export default ...

不同

前者返回...的模块结构,而后者返回{default: ...}的模块结构