Эквивалентны ли "Функции со стрелками" и "Функции".

javascript ecmascript-6 arrow-functions


Функции стрелок в ES2015 обеспечивают более лаконичный синтаксис.

  • Могу ли я теперь заменить все выражения деклараций функций на функции со стрелками?
  • На что я должен обратить внимание?

Examples:

Функция конструктора

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: () => {
    // ...
  }
};

Callbacks

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

// vs

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

вариадические функции

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

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



Answer 1 Felix Kling


ДЛ: Нет! Функции стрелок и объявления / выражения функций не эквивалентны и не могут быть заменены вслепую.
Если функция, которую вы хотите заменить, не использует this , arguments и не вызывается с new , тогда да.


Как часто: это зависит . Функции со стрелками ведут себя иначе, чем объявления / выражения функций, поэтому давайте сначала рассмотрим различия:

1. Лексический this и arguments

Функции со стрелками не имеют своих привязок this или arguments . Вместо этого эти идентификаторы разрешаются в лексической области, как и любая другая переменная. Это означает, что внутри функции стрелки arguments this и arguments ссылаются на значения this и arguments в среде, в которой определена функция стрелки (то есть «вне» функции стрелки):

// 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 относится к this из createObject самого.

Это делает функции стрелок полезными, если вам нужен доступ к this из текущей среды:

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

Если вы не очень знакомы с this , подумайте о прочтении

2. Функции стрелок нельзя вызывать с new

ES2015 различает между функциями, которые называют в состоянии и функции, которые сооружать состоянии. Если функция конструируема, ее можно вызвать с помощью new , то есть new User() . Если функция вызывается, ее можно вызывать без new (т. Е. Обычного вызова функции).

Функции,созданные с помощью выражений деклараций функций,являются как конструктивными,так и вызываемыми.
Функции стрелок (и методы) доступны только для вызова. конструкторы class являются только конструируемыми.

Если вы пытаетесь вызвать не вызываемую функцию или построить неконструктивную функцию,вы получите ошибку во время выполнения.


Зная это,мы можем заявить следующее.

Replaceable:

  • Функции, которые не используют this или arguments .
  • Функции, которые используются с .bind(this)

Не подлежит замене:

  • Конструкторские функции
  • Функция / методы добавлены в прототип (потому что они обычно используют this )
  • Функции Variadic (если они используют arguments (см. Ниже))

Давайте рассмотрим это подробнее на ваших примерах:

Функция конструктора

Это не будет работать, потому что функции стрелок не могут быть вызваны с new . Продолжайте использовать объявление функции / выражение или использовать class .

Методы прототипа

Скорее всего, нет, потому что методы-прототипы обычно используют this для доступа к экземпляру. Если они не используют this , то вы можете заменить его. Однако, если вам важен краткий синтаксис, используйте class с его кратким синтаксисом метода:

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

  getName() {
    return this.name;
  }
}

Методы объекта

Аналогично для методов в литерале объекта. Если метод хочет ссылаться на сам объект через this , продолжайте использовать выражения функции или используйте синтаксис нового метода:

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

Callbacks

Это зависит. Вам определенно следует заменить его, если вы используете псевдоним внешний this или используете .bind(this) :

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

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

Но: если код, который вызывает обратный вызов, явно устанавливает this конкретное значение, как это часто бывает с обработчиками событий, особенно с jQuery, и обратный вызов использует this (или arguments ), вы не можете использовать функцию стрелки!

Вариадические функции

Так как функции стрелок не имеют своих собственных arguments , вы не можете просто заменить их функцией стрелок. Однако ES2015 представляет альтернативу использованию arguments : параметр rest .

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

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

Похожий вопрос:

Дополнительные ресурсы:




Answer 2 Ashutosh


Функции стрелок => лучшая функция ES6 на данный момент. Они являются чрезвычайно мощным дополнением к ES6, которое я постоянно использую.

Подождите, вы не можете использовать функцию стрелки везде в вашем коде, она не будет работать во всех случаях, таких как this где функции стрелки не могут быть использованы. Без сомнения, функция стрелки является отличным дополнением и обеспечивает простоту кода.

Но вы не можете использовать функцию стрелки, когда требуется динамический контекст: определение методов, создание объектов с помощью конструкторов, получение цели из этого при обработке событий.

Функции стрелок НЕ должны использоваться,потому что:

  1. У них this

    Он использует «лексическую область видимости», чтобы выяснить, каким должно быть значение « this ». В простом слове лексическая область видимости использует « this » изнутри тела функции.

  2. У них нет arguments

    Функции стрелок не имеют объекта arguments . Но та же функциональность может быть достигнута с помощью параметров отдыха.

    let sum = (...args) => args.reduce((x, y) => x + y, 0) sum(3, 3, 1) // output - 7 `

  3. Они не могут быть использованы с new

    Функции стрелок не могут быть конструкциями,потому что у них нет свойства прототипа.

Когда использовать функцию со стрелкой,а когда нет:

  1. Не используйте функцию добавления в качестве свойства в буквальном смысле объекта,потому что мы не можем получить доступ к этому.
  2. Выражения функций лучше всего подходят для объектных методов. Стрелка функция лучше всего подходит для обратных вызовов или методов , как map , reduce или forEach .
  3. Используйте объявления функций для функций, которые вы вызываете по имени (потому что они подняты).
  4. Используйте функции стрелок для обратных вызовов (потому что они,как правило,триггерные).