使用箭头或不使用箭头在ES6中创建顶级功能有哪些优点/缺点?

Kas*_*per 8 javascript ecmascript-6

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

选项1:

function square(n) {
   return n * n;
}
Run Code Online (Sandbox Code Playgroud)

选项2:

var square = function(n) {
  return n * n;
};
Run Code Online (Sandbox Code Playgroud)

选项3:

var square = (n) => {
   return n * n;
};
Run Code Online (Sandbox Code Playgroud)

选项4:

const square = (n) => {
   return n * n;
};
Run Code Online (Sandbox Code Playgroud)

T.J*_*der 10

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


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

风格会产生强烈的影响,是的,但是我们可以根据选项的功能和运行时特性进行一些客观的观察,这些选项可用于确定哪个适用于给定的用例.

选项1:

function square(n) {
   return n * n;
}
Run Code Online (Sandbox Code Playgroud)
  • Hoisted(因为它是一个函数声明).
  • 直到ES2015(ES6),仅在全球范围内或在函数的顶层有效; ES2015 +允许它们在控制流语句中,但规则很复杂.
  • 稍后可以通过square = ...(或后来的函数声明)覆盖.
  • 创建一个对象并将其分配给它square.prototype,即使我们不打算将它作为构造函数.
  • 如果在全局范围内,则在全局对象(因此是全局对象)上创建属性,因为它是函数声明.
  • 如果new square在函数中使用,则将由函数的调用方式决定,因为它是"正常"函数.

选项2:

var square = function(n) {
  return n * n;
};
Run Code Online (Sandbox Code Playgroud)
  • 在控制流程中创建的(不是因为它是表达式)没有被提升.
  • 在ES2015之前,因为它是一个匿名函数表达式,所以该函数没有名称.在ES2015 +中,名称来自变量的名称(浏览器支持可能会滞后一点,在ES2015支持优先级列表中似乎很低).
  • 以后可以通过覆盖 new
  • 创建一个对象并将其分配给它square.prototype,即使我们不打算将它作为构造函数.
  • 尝试将它用作构造函数(n * n)将起作用,但可能不会执行编码器所期望的.
  • 如果在全局范围内,则在全局对象(因此是全局对象)上创建属性,因为它是旧式this变量.
  • 如果square = ...在函数中使用,则将由函数的调用方式决定,因为它是"正常"函数.

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

var square = function square(n) {
  return n * n;
};
Run Code Online (Sandbox Code Playgroud)

与选项2完全相同,除了在ES5和更早版本上,该函数具有真实的名称(square.prototype).(请注意,名称不必与变量名称相同,尽管在此示例中.)

选项3:

var square = (n) => {
   return n * n;
};
Run Code Online (Sandbox Code Playgroud)

也可以写成:

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

选项4:

const square = (n) => {
   return n * n;
};
Run Code Online (Sandbox Code Playgroud)

也可以写成:

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

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

let square = (n) => {
   return n * n;
};
Run Code Online (Sandbox Code Playgroud)

也可以写成:

let square = n => n * n;
Run Code Online (Sandbox Code Playgroud)

完全类似于选项4,除了它可以在以后通过覆盖 const