Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
421 views
in Technique[技术] by (71.8m points)

javascript - “箭头功能”和“功能”是否等效/可互换?(Are 'Arrow Functions' and 'Functions' equivalent / exchangeable?)

Arrow functions in ES2015 provide a more concise syntax.

(ES2015中的箭头函数提供了更简洁的语法。)

  • Can I replace all my function declarations / expressions with arrow functions now?

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

  • What do I have to look out for?

    (我要注意什么?)

Examples:

(例子:)

Constructor function

(构造函数)

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

// vs

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

Prototype methods

(原型方法)

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

// vs

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

Object (literal) methods

(对象(文字)方法)

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

// vs

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

Callbacks

(回呼)

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

// vs

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

Variadic functions

(可变函数)

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

// vs
const sum = (...args) => {
  // ...
};
  ask by Felix Kling translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

tl;dr: No!

(tl; dr: 不!)

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.

(如果您要替换的函数使用thisarguments并且未使用new arguments ,则为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. Lexical this and arguments

(1.词汇thisarguments)

Arrow functions don't have their own this or arguments binding.

(箭头函数没有自己的thisarguments绑定。)

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 (ie "outside" the arrow function):

(这意味着在arrow函数中, thisarguments指的是定义 arrow函数的环境中的thisarguments的值(即arrow函数的“外部”):)

 // 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 

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

(在函数表达式的情况下, this是指在createObject内部创建的对象。)

In the arrow function case, this refers to this of createObject itself.

(在箭头功能的情况下, this指的是thiscreateObject本身。)

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

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

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

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

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

(请注意 ,这也意味着这是不可能的设置箭头的功能是this.bind.call 。)

If you are not very familiar with this , consider reading

(如果你不是很熟悉this ,可以阅读)

2. Arrow functions cannot be called with new

(2.箭头函数不能用new调用)

ES2015 distinguishes between functions that are call able and functions that are construct able.

(ES2015区分了可调用的功能和可构造的功能。)

If a function is constructable, it can be called with new , ie new User() .

(如果一个函数是可构造的,则可以使用new ,即new User()来调用它。)

If a function is callable, it can be called without new (ie normal function call).

(如果一个函数是可调用的,则可以在不使用new函数的情况下对其进行调用(即正常的函数调用)。)

Functions created through function declarations / expressions are both constructable and callable.

(通过函数声明/表达式创建的函数是可构造的和可调用的。)


Arrow functions (and methods) are only callable.

(箭头函数(和方法)只能调用。)

class constructors are only constructable.

(class构造函数只能构造。)

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.

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

Replaceable:

(可更换的:)

  • Functions that don't use this or arguments .

    (不使用thisarguments 。)

  • Functions that are used with .bind(this)

    (与.bind(this)一起使用的函数)

Not replaceable:

(不可更换:)

  • Constructor functions

    (构造函数)

  • Function / methods added to a prototype (because they usually use this )

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

  • Variadic functions (if they use arguments (see below))

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


Lets have a closer look at this using your examples:

(让我们使用您的示例仔细看一下:)

Constructor function

(构造函数)

This won't work because arrow functions cannot be called with new .

(这将无法正常工作,因为无法使用new调用箭头函数。)

Keep using a function declaration / expression or use class .

(继续使用函数声明/表达式或使用class 。)

Prototype methods

(原型方法)

Most likely not, because prototype methods usually use this to access the instance.

(很有可能不是,因为原型方法通常使用this来访问实例。)

If they don't use this , then you can replace it.

(如果他们不使用this ,那么你就可以取代它。)

However, if you primarily care for concise syntax, use class with its concise method syntax:

(但是,如果您主要关心简洁的语法,请使用class及其简洁的方法语法:)

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

  getName() {
    return this.name;
  }
}

Object methods

(对象方法)

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:

(如果方法要通过this引用对象本身,请继续使用函数表达式,或使用新的方法语法:)

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

Callbacks

(回呼)

It depends.

(这取决于。)

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

(如果您要别名外部this或使用.bind(this) ,则绝对应该替换它:)

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

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

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!

(但是:如果调用回调的代码将事件显式地this值设置为特定值(在事件处理程序中,尤其是在jQuery中),并且回调使用this (或arguments ), 则不能使用箭头函数!)

Variadic functions

(可变函数)

Since arrow functions don't have their own arguments , you cannot simply replace them with an arrow function.

(由于箭头函数没有自己的arguments ,因此不能简单地将其替换为箭头函数。)

However, ES2015 introduces an alternative to using arguments : the rest parameter .

(但是,ES2015引入了使用arguments的替代方法: rest参数 。)

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

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

Related question:

(相关问题:)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...