【问题标题】:What are the advantages/disadvantages for creating a top level function in ES6 with arrows or without?在 ES6 中创建带箭头或不带箭头的顶级函数有哪些优点/缺点?
【发布时间】:2016-11-23 14:34:49
【问题描述】:

以这些不同的方式在 ES6/ES2015 中创建顶级函数有哪些优点/缺点?或者这只是品味/风格指南等问题?

选项 1:

function square(n) {
   return n * n;
}

选项 2:

var square = function(n) {
  return n * n;
};

选项 3:

var square = (n) => {
   return n * n;
};

选项 4:

const square = (n) => {
   return n * n;
};

【问题讨论】:

标签: javascript ecmascript-6


【解决方案1】:

注意:我已将此作为社区 wiki 发布,我们都可以添加到列表中,澄清等。请不要意见。 strong> 保持客观。


或者这只是品味/风格指南等问题?

样式会产生很大的影响,是的,但是我们可以根据选项的功能和运行时特性做出一些客观的观察,这些观察可以用来决定哪个适合给定的用例。

选项 1:

function square(n) {
   return n * n;
}
  • 已提升(因为它是函数声明)。
  • 直到 ES2015 (ES6),仅在全局范围或函数顶层有效; ES2015+ 允许在控制流语句中使用它们,但规则很复杂。
  • 以后可以通过square = ...(或以后的函数声明)覆盖。
  • 创建一个对象并将其分配给square.prototype,即使我们不打算将其用作构造函数。
  • 尝试将其用作构造函数 (new square) 将起作用,但可能不会达到编码员的预期:new 操作的结果将是一个使用 square.prototype 作为其原型的对象(以及函数的n * n 的返回值被丢弃)。
  • 如果在全局范围内,则在全局对象(因此是全局)上创建一个属性,因为它是一个函数声明。
  • 如果在函数中使用了this,则取决于函数的调用方式,因为它是“普通”函数。

选项 2:

var square = function(n) {
  return n * n;
};
  • 未提升(因为它是一个表达式),在控制流期间创建。
  • 在 ES2015 之前,由于它是一个 匿名 函数表达式,因此该函数没有名称。在 ES2015+ 中,名称来源于变量的名称​​(浏览器支持可能有点滞后,在 ES2015 支持优先级列表中似乎较低)
  • 以后可以通过square = ... 覆盖
  • 创建一个对象并将其分配给square.prototype,即使我们不打算将其用作构造函数。
  • 尝试将其用作构造函数 (new square) 会起作用,但可能无法达到编码员的预期(请参阅函数声明的注释)。
  • 如果在全局范围内,则在全局对象(因此是全局对象)上创建一个属性,因为它是旧式 var 变量。
  • 如果在函数中使用this,则取决于函数的调用方式,因为它是“普通”函数。

选项 2.5:(我已经添加了这个)

var square = function square(n) {
  return n * n;
};

与选项 2 完全一样,除了在 ES5 和更早版本上,该函数有一个真实的名称 (square)。 (请注意,名称不必与变量的名称相同,尽管在此示例中。)(IE8 和更早版本中的错误最终会创建两个函数,而不仅仅是一个;this blog post 中的详细信息由 TJ Crowder [此答案的主要作者]。)

选项 3:

var square = (n) => {
   return n * n;
};

也可以写成:

var square = n => n * n;
  • 未提升(因为它是一个表达式),在控制流期间创建。
  • 函数名来源于变量名(浏览器支持可能有点滞后,在 ES2015 支持优先级列表中似乎较低)
  • 以后可以通过square = ... 覆盖
  • 创建对象并将其分配给square.prototype
  • 尝试将其用作构造函数 (new square) 将失败并显示信息错误 (TypeError: square is not a constructor)。
  • 没有arguments(但如果您需要arguments 功能,可以使用其余参数代替)。
  • 根据规范,调用它时需要“设置”的东西更少,因为它没有自己的this,也没有arguments。但是现代 JavaScript 引擎已经优化了 arguments 的创建,如果你不使用它,那么设置 this 不太可能是一个巨大的成本。
  • 如果在全局范围内,则在全局对象(因此是全局)上创建一个属性,因为它是一个旧式 var 变量。
  • 因为它是一个箭头函数,如果在函数中使用this,它将使用与定义函数的代码相同的this,因为箭头函数关闭 @987654353 @(而不是通过它们的调用方式来设置)。

选项 4:

const square = (n) => {
   return n * n;
};

也可以写成:

const square = n => n * n;
  • 未提升,在控制流期间创建
  • 函数名来源于变量名(浏览器支持可能有点滞后,在 ES2015 支持优先级列表中似乎较低)
  • 不能稍后通过square = ... 覆盖
  • 创建对象并将其分配给square.prototype
  • 尝试将其用作构造函数 (new square) 将失败并显示信息错误 (TypeError: square is not a constructor)。
  • 没有arguments(请参阅选项 3 的说明)。
  • 根据规范,调用它时需要“设置”的东西更少(请参阅选项 3 的注释)。
  • 如果在全局范围内,不会在全局对象上创建属性(但仍会创建全局),因为它是 ES2015+ const
  • 因为它是一个箭头函数,如果在函数中使用this,它将使用与定义函数的代码相同的this,因为箭头函数关闭 @987654364 @(而不是通过它们的调用方式来设置)。

选项 5:(我已经添加了这个)

let square = (n) => {
   return n * n;
};

也可以写成:

let square = n => n * n;

与选项 4 完全一样,只是以后可以通过square = ... 覆盖

【讨论】:

  • 既然是es2015+,那要不要加export default function呢?
  • @cswl:和第一个完全一样,只不过是导出的。
【解决方案2】:

旧函数和 ES6 箭头函数之间的两个主要区别是代码的长度(箭头函数在您的情况下减少了样板文件,并且 IMO 更优雅,因为您可以省略 return 关键字)以及这些函数的工作方式与context of the function call

我会将函数写为const square = n => n*n;。但一般来说,没有“在 ES6/ES2015 中创建顶级函数的首选方式”之类的东西。

【讨论】:

  • 好的,谢谢,我想这类问题更适合非正式聊天,而不是 stackoverflow,但再次感谢您的回复,它确实有帮助,至少现在我知道这只是意见-基于:)
  • 除非您已经阅读了关于 JS 函数的 上下文和范围 的内容,否则请阅读我添加到答案中的文章。它可能有用;)
  • @ŠimonRozsíval,我相信这个问题非常有价值,你的帖子不像一个答案。我投反对票并标记,因为这不是答案。
猜你喜欢
  • 2019-12-17
  • 2016-12-22
  • 2016-08-06
  • 2018-01-08
  • 2016-12-08
  • 2014-03-11
  • 1970-01-01
  • 2019-01-06
  • 1970-01-01
相关资源
最近更新 更多