从 ES6 模块导入函数表达式或函数声明有什么区别?

2024-05-30

据我了解(参见第 16.3.2.1 节 http://exploringjs.com/es6/ch_modules.html),ES6 允许函数/类导出操作数使用不同的语法。区别在于导出的函数是否需要在导入时解释为函数声明,在这种情况下,您可以编写:export default function () {} // (a)或作为函数表达式:export default (function () {}); // (b).

作为可能的相关旁注:我读到导入已被提升,但我不太确定这在这种情况下意味着什么。

以这个例子为例:

import foo from 'my_module'; // (c)

据我了解,上述语句会将我导出的函数保存在foo多变的。该变量是否被提升,或者是什么,何时?

最重要的是,有什么区别(在设置方面)foo) when my_module使用导出函数(a)当它使用导出时(b)?


你的问题有点复杂,但我会尽力解释一切。

让我们首先确定模块的一般工作方式。模块有一组导出的名称,每个名称都引用该模块中的一个局部变量。导出的名称不需要与本地绑定的名称相同。导出的名称之一可以是default,有专门用于模块仅导出单个内容的情况的特殊语法(导出和导入)。

我读到导入已被提升,但我不太确定这在这种情况下意味着什么:

import { foo } from 'my_module';

是的,进口报关单已悬挂。类似于var or function(实际上喜欢所有其他声明 https://stackoverflow.com/a/31222689/1048572) 标识符foo在执行模块中的任何语句之前,从一开始就可用。事实上,绑定甚至是在声明的绑定之前创建的variables.

区别在于它们的初始化方式:

  • vars 初始化为undefined
  • functions and function*s 用函数对象初始化
  • let, const and classes 未初始化
  • 导入绑定甚至没有真正初始化,它们被创建为指向导出名称在导入模块中引用的局部变量的指针
  • 导入模块 (import * as …)用模块对象初始化(其属性也是这样的指针)

When is foo设置为引用我的导出函数?

简短的回答:首先。

长答案:还没有真正确定。它是对导入模块中您希望保存该函数的局部变量的引用。当局部变量不存在时,它可能会改变const- 但我们通常不希望这样。通常它确实已经包含该功能,因为导入的模块之前已被完全评估导入它的模块是。所以如果你担心有问题var functionName = function() {} vs function functionName() {} https://stackoverflow.com/q/336859/1048572你可能会松一口气——没有。

现在回到你的标题问题:

ES6 模块中导出函数表达式和函数声明有什么区别?

没什么特别的,这两个方面实际上没有太大关系:

  • export声明将导出名称链接到模块范围内的局部变量
  • 像往常一样,模块范围内的所有变量都会被提升
  • 函数声明的初始化方式与通过函数表达式赋值的变量声明不同,as usual https://stackoverflow.com/q/336859/1048572

当然,仍然没有充分的理由不使用更多陈述性的函数声明无处不在;这在 ES6 模块中与以前没有什么不同。如果有的话,使用函数表达式的理由甚至可能更少,因为声明涵盖了所有内容:

/* for named exports */
export function foo() {…}

// or
function foo() {…}
export {foo as foo}
/* for default exports */
export default function foo() {…}

// or
function foo() {…}
export {foo as default}

// or
function foo() {…}
export default foo;

// or
export default function() {…}

好的,最后两个默认导出声明实际上与前两个有点不同。链接到导出名称的本地标识符default is not foo, but *default*- 不能重新分配。这在最后一种情况下是有意义的(没有名字foo),但在倒数第二个例子中你应该注意到foo实际上只是一个本地别名,而不是导出的变量本身。我建议不要使用这种模式。

哦,在你问之前:是的,最后一个默认导出实际上也是一个函数声明,而不是一个表达式。一个匿名函数声明。这是 ES6 的新功能:-)

那么到底有什么区别export default function () {} and export default (function () {});

它们对于每种用途都几乎相同。它们是匿名函数,具有.name财产"default",由那个特殊的*default*导出名称的绑定default指向匿名导出值。
它们唯一的区别是提升 - 声明将在模块顶部实例化其函数,只有在模块代码执行到达语句时才会计算表达式。但是,由于没有具有可访问名称的变量,因此这种行为是不可观察的,除了一种非常奇怪的特殊情况:导入自身的模块。嗯,是的。

import def from "myself";
def(); // works and logs the message
export default function() {
    console.log("I did it!");
}
import def from "myself";
def(); // throws a TypeError about `def` not being a function
export default (function() {
    console.log("I tried!");
});

无论如何,你真的不应该做这两件事。如果您想在模块中使用导出函数,请在其声明中为其指定名称。

既然如此,为什么要同时使用这两种语法呢?

发生。它是allowed通过规范,因为它没有制定额外的例外来禁止某些无意义的事情。这是不打算要使用的。在这种情况下,规范甚至明确不允许function and class中的表达式export default语句并将它们视为声明。通过使用分组运算符,您发现了一个漏洞。做得好。不要滥用它。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从 ES6 模块导入函数表达式或函数声明有什么区别? 的相关文章

随机推荐