“箭头功能”和“功能”是否等效/可互换? [英] Are 'Arrow Functions' and 'Functions' equivalent / interchangeable?

查看:87
本文介绍了“箭头功能”和“功能”是否等效/可互换?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

ES2015中的箭头功能提供了更简洁的语法。

Arrow functions in ES2015 provide a more concise syntax.


  • 我现在可以用箭头函数替换所有函数声明/表达式吗?

  • 我要寻找什么?

示例:

构造函数

function User(name) {
  this.name = name;
}

// vs

const User = name => {
  this.name = name;
};

原型方法

User.prototype.getName = function() {
  return this.name;
};

// vs

User.prototype.getName = () => this.name;

对象(文字)方法

const obj = {
  getName: function() {
    // ...
  }
};

// vs

const obj = {
  getName: () => {
    // ...
  }
};

回调

setTimeout(function() {
  // ...
}, 500);

// vs

setTimeout(() => {
  // ...
}, 500);

可变函数

function sum() {
  let args = [].slice.call(arguments);
  // ...
}

// vs
const sum = (...args) => {
  // ...
};


推荐答案

tl; dr: 否!箭头函数和函数声明/表达式不等效,不能盲目替换。

如果要替换的函数不使用 not 参数,并且不使用 new 进行调用,然后是的。

tl;dr: No! Arrow functions and function declarations / expressions are not equivalent and cannot be replaced blindly.
If the function you want to replace does not use this, arguments and is not called with new, then yes.

通常:这取决于。箭头函数的行为不同于函数声明/表达式的行为,因此让我们首先看一下它们之间的区别:

As so often: it depends. Arrow functions have different behavior than function declarations / expressions, so let's have a look at the differences first:

1。词法 this arguments

1. Lexical this and arguments

箭头函数不有自己的 this arguments 绑定。相反,这些标识符像任何其他变量一样在词法范围内解析。这意味着在箭头函数中, this arguments 引用 this arguments 的环境中,箭头功能是在定义中定义的(即外部箭头功能):

Arrow functions don't have their own this or arguments binding. Instead, those identifiers are resolved in the lexical scope like any other variable. That means that inside an arrow function, this and arguments refer to the values of this and arguments in the environment the arrow function is defined in (i.e. "outside" the arrow function):

// Example using a function expression
function createObject() {
  console.log('Inside `createObject`:', this.foo);
  return {
    foo: 42,
    bar: function() {
      console.log('Inside `bar`:', this.foo);
    },
  };
}

createObject.call({foo: 21}).bar(); // override `this` inside createObject

// Example using a arrow function
function createObject() {
  console.log('Inside `createObject`:', this.foo);
  return {
    foo: 42,
    bar: () => console.log('Inside `bar`:', this.foo),
  };
}

createObject.call({foo: 21}).bar(); // override `this` inside createObject

在函数表达式中, this 表示在 createObject 内部创建的对象。在箭头函数情况下, this 表示 createObject this

In the function expression case, this refers to the object that was created inside the createObject. In the arrow function case, this refers to this of createObject itself.

如果需要访问当前环境的 this ,这会使箭头功能有用:

This makes arrow functions useful if you need to access the this of the current environment:

// currently common pattern
var that = this;
getData(function(data) {
  that.data = data;
});

// better alternative with arrow functions
getData(data => {
  this.data = data;
});

注意,这也意味着不能设置箭头函数的 this .bind .call

Note that this also means that is not possible to set an arrow function's this with .bind or .call.

如果您不太熟悉,请考虑阅读

If you are not very familiar with this, consider reading

  • MDN - this
  • YDKJS - this & Object prototypes

2。无法使用 new

2. Arrow functions cannot be called with new

ES2015区分可调用 的函数和可以构造的功能。如果函数是可构造的,则可以使用 new 调用,即 new User()。如果一个函数是可调用的,则可以在不使用 new (即正常函数调用)的情况下对其进行调用。

ES2015 distinguishes between functions that are callable and functions that are constructable. If a function is constructable, it can be called with new, i.e. new User(). If a function is callable, it can be called without new (i.e. normal function call).

通过函数声明/表达式创建的函数既可构造又可调用。

箭头函数(和方法)仅可调用。
构造函数只能构造。

Functions created through function declarations / expressions are both constructable and callable.
Arrow functions (and methods) are only callable. class constructors are only constructable.

如果您试图调用不可调用的函数或构造一个不可调用的函数可构造函数,您会遇到运行时错误。

If you are trying to call a non-callable function or to construct a non-constructable function, you will get a runtime error.

知道这一点后,我们可以陈述以下内容。

Knowing this, we can state the following.

可替换:


  • 不使用 this 参数的函数

  • .bind(this)

  • Functions that don't use this or arguments.
  • Functions that are used with .bind(this)

不可可替换:


  • 构造函数

  • 添加到原型的函数/方法(因为它们通常使用 this

  • 可变参数函数(如果它们使用参数(见下文))

  • Constructor functions
  • Function / methods added to a prototype (because they usually use this)
  • Variadic functions (if they use arguments (see below))

让我们用您的例子仔细研究一下:

Lets have a closer look at this using your examples:

构造函数

这是行不通的,因为箭头函数不能用调用新。继续使用函数声明/表达式或使用 class

This won't work because arrow functions cannot be called with new. Keep using a function declaration / expression or use class.

原型方法

很有可能不会,因为原型方法通常使用 this 来访问实例。如果他们不使用 this ,则可以将其替换。但是,如果您主要关心简洁的语法,请使用 class 及其简洁的方法语法:

Most likely not, because prototype methods usually use this to access the instance. If they don't use this, then you can replace it. However, if you primarily care for concise syntax, use class with its concise method syntax:

class User {
  constructor(name) {
    this.name = name;
  }
  
  getName() {
    return this.name;
  }
}

对象方法

与对象文字中的方法类似。如果方法想通过 this 引用对象本身,请继续使用函数表达式或使用新的方法语法:

Similarly for methods in an object literal. If the method wants to reference the object itself via this, keep using function expressions, or use the new method syntax:

const obj = {
  getName() {
    // ...
  },
};

回调

这取决于。如果要别名外部 this 或使用 .bind(this)

It depends. You should definitely replace it if you are aliasing the outer this or are using .bind(this):

// old
setTimeout(function() {
  // ...
}.bind(this), 500);

// new
setTimeout(() => {
  // ...
}, 500);

但是:如果调用回调的代码明确设置了 this 设置为特定值,事件处理程序(尤其是jQuery)通常如此,并且回调使用 this (或参数),则不能使用箭头功能!

But: If the code which calls the callback explicitly sets this to a specific value, as is often the case with event handlers, especially with jQuery, and the callback uses this (or arguments), you cannot use an arrow function!

可变参数函数

由于箭头函数没有自己的自变量,因此不能简单地将它们替换为箭头函数。但是,ES2015引入了使用 arguments 的替代方法:休息参数

Since arrow functions don't have their own arguments, you cannot simply replace them with an arrow function. However, ES2015 introduces an alternative to using arguments: the rest parameter.

// old
function sum() {
  let args = [].slice.call(arguments);
  // ...
}

// new
const sum = (...args) => {
  // ...
};




相关问题:


Related question:

  • When should I use Arrow functions in ECMAScript 6?
  • Do ES6 arrow functions have their own arguments or not?
  • What are the differences (if any) between ES6 arrow functions and functions bound with Function.prototype.bind?
  • How to use arrow functions (public class fields) as class methods?

其他资源:

  • MDN - Arrow functions
  • YDKJS - Arrow functions

这篇关于“箭头功能”和“功能”是否等效/可互换?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆