且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

在带有箭头或不带箭头的ES6中创建***功能有哪些优点/缺点?

更新时间:2022-12-27 12:11:20

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







或者这只是一个味道/风格指南等的问题?


风格有很强的影响,是的,但是有一些客观的观察,我们可以在功能和运行时特性方面进行选择,这些选项可以用来决定哪个是适用于给定的用例。


选项1:

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





  • Hoisted (因为它是一个函数声明)。

  • 直到ES2015(ES6),仅在全局范围或功能顶层有效; ES2015 +允许他们在控制流程语句中,但规则很复杂。

  • 可以通过 square = ... (或稍后的函数声明)。

  • 创建一个对象并将其分配给 square.prototype ,即使我们不打算作为一个构造函数。

  • 如果在全局范围内,由于它是一个函数声明,所以在全局对象(因此是全局)上创建一个属性。

  • 如果在函数中使用了这个,那么它将由函数调用决定,因为它是一个正常函数。




选项2:

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





  • 未提起(因为它是表达式),在控制流程中创建。

  • 直到ES2015,由于它是一个匿名函数表达式,该函数没有名称。在ES2015 +中,该名称来源于变量的名称​​(浏览器支持可能会稍微延迟一些,ES2015支持优先级列表似乎很低)

  • 可以通过 square = ...

  • 创建一个对象并将其分配给 square.prototype ,即使我们不打算将其作为构造函数。

  • 尝试将其用作构造函数( new square )将工作,但可能不会执行编码器的预期。

  • 如果在全局范围内,在全局对象(因此是全局)上创建一个属性,因为它是一个旧式的 var 变量。

  • 如果这个功能,它将由函数调用决定,因为它是一个正常函数。




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

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


完全类似于选项2,除了在ES5和更早版本,函数有一个真实的名字( square )。 (请注意,该名称不一定与变量的名称相同,尽管在此示例中。)


选项3:

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


还可以写:

  var square = n => n * n; 




  • 在控制流程中创建时未悬挂(因为它是一个表达式)

  • 该函数的名称来源于变量的名称​​(浏览器支持可能会延迟一点,在ES2015支持优先级列表中似乎很低)

  • 可以通过 square = ...

  • / em>创建一个对象并将其分配给 square.prototype

  • 尝试将其用作构造函数( new square )将失败,并显示一条信息错误( TypeError:square不是构造函数)。

  • 没有参数(但是如果需要参数功能,则可以使用rest参数。 li>
  • 每个规格,调用它时需要更少的设置,因为它没有自己的这个参数。但现代JavaScript引擎已经优化了参数的创建,如果您不使用它,并且不太可能设置这个是一个显着的成本。

  • 如果在全局范围内,在全局对象(因此是全局)上创建一个属性,因为它是一个旧式的 var 变量

  • 因为它是一个箭头函数,如果这个在函数中使用,它将使用由于箭头函数关闭 这个这个这个 >(而不是按照他们的名字设定)。




选项4: p>

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


还可以写:

  const square = n => n * n; 




  • 在控制流程中创建时未悬挂

  • 该函数的名称来自变量的名称​​(浏览器支持可能会稍微延迟一点,ES2015支持优先级列表似乎很低)

  • 不能稍后通过 square = ...

  • t 创建一个对象并将其分配给 square.prototype

  • 尝试将其用作构造函数( new square )将失败,并显示一条内容丰富的错误( TypeError:square不是构造函数)。

  • 没有参数(参见选项3中的注释)。

  • 每个规格,需要更少的事情设置(请参阅选项3中的注释)。

  • 如果在全局范围内,在全局对象上创建一个属性(但仍然创建一个全局),因为它是一个ES2015 + const

  • 因为它是一个箭头函数,如果这个在函数中使用,它将使用相同的这个作为函数定义的代码,因为箭头 这个(而不是通过调用它们来设置)。




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

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


还可以写:

  let square = n => n * n; 

与选项4完全相同,只能稍后通过 square =覆盖。 ..


What are the advantages/disadvantages to create a top level function in ES6/ES2015 in those different ways? Or is this just a matter of taste/style guide etc?

Option 1:

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

Option 2:

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

Option 3:

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

Option 4:

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

Note: I've posted this as a community wiki, we can all add to the list, clarify, etc. Please no opinions. Keep it objective.


Or is this just a matter of taste/style guide etc?

There will be a strong influence of style, yes, but there are some objective observations we can make in terms of the functionality and runtime characteristics of the options that can be used to decide which is appropriate for a given use-case.

Option 1:

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

  • Hoisted (because it's a function declaration).
  • Until ES2015 (ES6), only valid at global scope or at the top-level of a function; ES2015+ allows them within control flow statements, but the rules are complex.
  • Can be overwritten later via square = ... (or a later function declaration).
  • Creates an object and assigns it to square.prototype, even though we don't intend it to be a constructor.
  • If at global scope, creates a property on the global object (and thus, a global) because it's a function declaration.
  • If this were used within the function, it would be determined by how the function is called, as it's a "normal" function.

Option 2:

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

  • Not hoisted (because it's an expression), created during control flow.
  • Until ES2015, since it's an anonymous function expression, the function didn't have a name. In ES2015+, the name is derived from the variable's name (browser support may lag a bit, it seems to be low on the ES2015 support priority list).
  • Can be overwritten later via square = ...
  • Creates an object and assigns it to square.prototype, even though we don't intend it to be a constructor.
  • Attempts to use it as a constructor (new square) will work, but probably not do what the coder expected.
  • If at global scope, creates a property on the global object (and thus, a global) since it's an old-style var variable.
  • If this were used within the function, it would be determined by how the function is called, as it's a "normal" function.

Option 2.5: (I've added this one)

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

Exactly like Option 2, except that on ES5 and earlier, the function has a true name (square). (Note that the name doesn't have to be the same as the name of the variable, although it is in this example.)

Option 3:

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

Could also be written:

var square = n => n * n;

  • Not hoisted (because it's an expression), created during control flow.
  • The function's name is derived from the variable's name (browser support may lag a bit, it seems to be low on the ES2015 support priority list).
  • Can be overwritten later via square = ...
  • Doesn't create an object and assign it to square.prototype.
  • Attempts to use it as a constructor (new square) will fail with an informative error (TypeError: square is not a constructor).
  • Doesn't have arguments (but you can use rest arguments instead if you need arguments functionality).
  • Per spec, requires fewer things to be "set up" when calling it, as it doesn't have its own this and doesn't have arguments. But modern JavaScript engines already optimize-out the creation of arguments if you don't use it, and it's unlikely setting up this is a significant cost.
  • If at global scope, creates a property on the global object (and thus, a global) since it's an old-style var variable.
  • Because it's an arrow function, if this were used within the function, it would use the same this as the code where the function is defined, since arrow functions close over this (rather than having it set by how they're called).

Option 4:

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

Could also be written:

const square = n => n * n;

  • Not hoisted, created during control flow
  • The function's name is derived from the variable's name (browser support may lag a bit, it seems to be low on the ES2015 support priority list).
  • Can't be overwritten later via square = ...
  • Doesn't create an object and assign it to square.prototype.
  • Attempts to use it as a constructor (new square) will fail with an informative error (TypeError: square is not a constructor).
  • Doesn't have arguments (see notes on Option 3).
  • Per spec, requires fewer things to be "set up" when calling it (see notes on Option 3).
  • If at global scope, doesn't create a property on the global object (but still creates a global), since it's an ES2015+ const.
  • Because it's an arrow function, if this were used within the function, it would use the same this as the code where the function is defined, since arrow functions close over this (rather than having it set by how they're called).

Option 5: (I've added this one)

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

Could also be written:

let square = n => n * n;

Exactly like Option 4, except it can be overwritten later via square = ...