Когда не следует использовать стрелочные функции

JavaScript ECMAScript 6

оригинал:Рисовое путешествие avlutin.com/Мне очень-не-к…

Переводчик: Front-end Xiaozhi

Чем больше вы знаете, тем больше вы не знаете

Ставьте лайк и смотрите снова, формируйте привычку


эта статьяГитхаб:GitHub.com/QQ449245884…Он был включен в вышеизложенное, и более ранние статьи с высокими похвалами были классифицированы, а также было систематизировано множество моих документов и учебных материалов. Добро пожаловать в Star and Perfect. Вы можете обратиться в тестовый центр для ознакомления во время собеседования. Надеюсь, у нас что-то получится вместе.

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

За прошедшие годы ES6 вывел удобство использования JS на новый уровень: стрелочные функции, классы и многое другое — это здорово.

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

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

1. Определите методы объекта

В JS методы — это функции, хранящиеся в свойствах объекта. При вызове этого методаthisУкажет на объект, которому принадлежит метод.

Object literal

Из-за короткого синтаксиса стрелочной функции привлекательно использовать ее для определения методов, давайте попробуем:

const calculate = {
  array: [1, 2, 3],
  sum: () => {
    console.log(this === window); // => true
    return this.array.reduce((result, item) => result + item);
  }
};
console.log(this === window); // => true
// Throws "TypeError: Cannot read property 'reduce' of undefined"
calculate.sum();

calculate.sumМетоды определяются с помощью стрелочных функций. Но при звонкеcalculate.sum()броситTypeError,потому чтоthis.arrayдляundefined.

при звонкеcalculateметоды на объектахsum(), контекст по-прежнемуwindow. Это происходит потому, что стрелочные функции лексически связывают контекст сwindowобъект.

воплощать в жизньthis.arrayЭквивалентноwindow.array,этоundefined.

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

const calculate = {  
  array: [1, 2, 3],
  sum() {
    console.log(this === calculate); // => true
    return this.array.reduce((result, item) => result + item);
  }
};
calculate.sum(); // => 6

потому чтоsumявляется обычной функцией, поэтому при вызовеcalculate.sum()Времяthisдаcalculateобъект.this.arrayявляется ссылкой на массив, поэтому сумма элементов вычисляется правильно:6.

Object prototype

Те же правила применяются к определению методов объектов-прототипов. Используйте функцию стрелки, чтобы определитьsayCatNameметод,thisнаправлениеwindow

function MyCat(name) {
  this.catName = name;
}
MyCat.prototype.sayCatName = () => {
  console.log(this === window); // => true
  return this.catName;
};
const cat = new MyCat('Mew');
cat.sayCatName(); // => undefined

Определяйте выражения функций ранее:

function MyCat(name) {
  this.catName = name;
}
MyCat.prototype.sayCatName = function() {
  console.log(this === cat); // => true
  return this.catName;
};
const cat = new MyCat('Mew');
cat.sayCatName(); // => 'Mew'

sayCatNameОбычная функция при вызове в качестве метода меняет контекст наcatОбъект:cat.sayCatName().

2. Функция обратного вызова динамического контекста

thisВ JS есть мощная функция, позволяющая изменять контекст в зависимости от того, как вызывается функция. Обычно контекст — это целевой объект, в котором происходит вызов, что делает код более естественным, чем то, что произошло с этим объектом.

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

Присоединение прослушивателей событий к элементам DOM — обычная задача клиентского программирования. Событие запускает функцию обработчика иthisВ качестве целевого элемента он недостаточно гибок, чтобы использовать здесь стрелочные функции.

В следующем примере делается попытка использовать стрелочные функции для такого обработчика:

const button = document.getElementById('myButton');
button.addEventListener('click', () => {
  console.log(this === window); // => true
  this.innerHTML = 'Clicked button';
});

в глобальном контекстеthisнаправлениеwindow. Когда происходит событие щелчка, браузер пытается вызвать функцию-обработчик с контекстом кнопки, но функция стрелки не меняет свой предопределенный контекст.this.innerHTMLэквивалентноwindow.innerHTML, бессмысленно.

Должно быть применено функциональное выражение, которое позволяет вносить изменения в зависимости от целевого элемента.this:

const button = document.getElementById('myButton');
button.addEventListener('click', function() {
  console.log(this === button); // => true
  this.innerHTML = 'Clicked button';
});

Когда пользователь нажимает кнопку, в функции обработчикаthisнаправлениеbutton. Отсюда вопрос.innerHTML = 'Clicked button'Правильно измените текст кнопки, чтобы он отражал состояние нажатия.

3. Вызвать конструктор

thisВ вызове конструкции находится только что созданный объект. при исполненииnew MyFunction()когда конструкторMyFunctionКонтекст — это новый объект:this instanceof MyFunction === true.

Уведомление, стрелочные функции нельзя использовать в качестве конструкторов. JavaScript неявно предотвращает это, генерируя исключения.

в любом случае,this- это настройка из окружающего контекста, а не только что созданного объекта. Другими словами, вызовы конструктора стрелочных функций бессмысленны и неоднозначны.

Давайте посмотрим, что произойдет, если мы попытаемся сделать это:

const Message = (text) => {
  this.text = text;
};
// Throws "TypeError: Message is not a constructor"
const helloMessage = new Message('Hello World!');

воплощать в жизньnew Message('Hello World!')MessageЯвляется стрелочной функцией, JavaScript выдаетTypeErrorошибка,MessageНе может использоваться в качестве конструктора.

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

const Message = function(text) {
  this.text = text;
};
const helloMessage = new Message('Hello World!');

сокращенный синтаксис

У стрелочных функций есть хорошее свойство опускать круглые скобки параметров.(), Масса блока{}, который возвращается, если тело функции содержит только один оператор. Это помогает писать очень короткие функции.

Профессор программирования в колледже автора дал студентам интересное задание: написать кратчайшую функцию для вычисления длины строки на языке C — отличный способ выучить и изучить новый язык.

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

В некотором смысле сокращенные функции становятся трудными для чтения, поэтому старайтесь не злоупотреблять ими. Давайте посмотрим на пример

const multiply = (a, b) => b === undefined ? b => a * b : a * b;
const double = multiply(2);
double(3);      // => 6
multiply(2, 3); // => 6

multiplyВозвращает результат умножения двух чисел или замыкание, привязанное к первому аргументу, для будущих операций умножения.

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

Чтобы сделать его более читабельным, необязательные фигурные скобки иreturnЗаявление или используйте регулярную функцию:

function multiply(a, b) {
  if (b === undefined) {
    return function(b) {
      return a * b;
    }
  }
  return a * b;
}
const double = multiply(2);
double(3);      // => 6
multiply(2, 3); // => 6

Хорошо найти баланс между краткостью и многословием, что делает код более интуитивным.

Суммировать

Без сомнения, стрелочные функции — отличное дополнение. При правильном использовании он заставляет переднюю часть использовать.bind()Или там, где попытка захватить контекст становится простой, это также упрощает код.

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

Ошибки, которые могут существовать после развертывания кода, не могут быть известны в режиме реального времени.Чтобы решить эти ошибки впоследствии, много времени тратится на отладку журнала.Кстати, я рекомендую всем полезный инструмент мониторинга ошибок.Fundebug.

Коммуникация (приглашаем вступить в группу, группа будет присылать красные конверты по рабочим дням, технология интерактивного обсуждения)

Статьи из серии галантерейных товаров резюмируются следующим образом: если вы чувствуете себя хорошо, нажмите «Звезда», добро пожаловать в группу, чтобы учиться друг у друга.

GitHub.com/QQ449245884…

Я Сяо Чжи, автор официального аккаунта "Moving the World",Продолжайте знакомить энтузиастов с передовыми технологиями. Я буду часто делиться тем, что я узнал и увидел, На пути продвижения, давайте подбадривать друг друга!

Обратите внимание на публичный аккаунт и отвечайте в фоновом режимеБлагосостояние, вы можете увидеть преимущества, вы знаете.

Приложение: Новая статья будет отправлена ​​в публичный аккаунт за сутки