Функция стрелки против объявления / выражения функции: они эквивалентны / заменяемы?




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




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



примеры:



конструктор функция



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;
553   2  

2 ответов:

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


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

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

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

// 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 конструкторы являются только конструктивными.

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


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

заменить:

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

не заменить:

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

давайте более подробно рассмотрим это, используя ваши примеры:

функции-конструктора

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

прототип методы

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

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

  getName() {
    return this.name;
  }
}

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

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

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

обратные вызовы

это зависит. Вы обязательно должны заменить его, если вы сглаживаете внешний this или .bind(this):

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

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

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

variadic функции

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

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

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

вопрос:

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

посмотрите на этот пример Plnkr

переменная this очень разные timesCalled увеличивается только на 1 при каждом вызове кнопки. Что отвечает на мой личный вопрос:

.click( () => { } )

и

.click(function() { })

оба создают одинаковое количество функций при использовании в цикле, как вы можете видеть из счетчика Guid в Plnkr.

Comments

    Ничего не найдено.