В чем разница между стрелочными функциями и обычными функциями внутри функциональных компонентов React (больше не использующих компоненты класса)?

Начиная с React Hooks, я решил отказаться от компонентов класса React. Сейчас я имею дело только с хуками и функциональными компонентами.

Простой вопрос:

Я понимаю разницу между использованием функции стрелки вместо обычной функции внутри тела класса. Функция стрелки автоматически привязывается (лексический это) к экземпляру моего класса, и мне не нужно привязывать ее в конструкторе. Это приятно.

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

function App() {

  // REGULAR FUNCTION
  function handleClick1() {
    console.info('handleClick1 executed...');
  }

  // ARROW FUNCTION
  const handleClick2 = () => {
    console.info('handleClick2 executed...');
  }

  return(
    <React.Fragment>
      <div className = {'div1'} onClick = {handleClick1}>
        Div 1 - Click me
      </div>
      <div className = {'div2'} onClick = {handleClick2}>
        Div 2 - Click me
      </div>
    </React.Fragment>
  );
}

ВОПРОС

Оба работают нормально.

Есть ли разница в производительности? Должен ли я предпочесть в одну сторону вместо другой? Они оба воссоздаются при каждом рендере, верно?


ПРИМЕЧАНИЕ О ВОЗМОЖНЫХ ДУБЛИКАТАХ

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


ФРАГМЕНТ КОДА ДЛЯ ТЕСТИРОВАНИЯ

function App() {
  
  function handleClick1() {
    console.info('handleClick1 executed...');
  }
  
  const handleClick2 = () => {
    console.info('handleClick2 executed...');
  }
  
  return(
    <React.Fragment>
      <div className = {'div1'} onClick = {handleClick1}>
        Div 1 - Click me
      </div>
      <div className = {'div2'} onClick = {handleClick2}>
        Div 2 - Click me
      </div>
    </React.Fragment>
  );
}

ReactDOM.render(<App/>, document.getElementById('root'));
.div1 {
  border: 1px solid blue;
  cursor: pointer;
}

.div2 {
  border: 1px solid blue;
  cursor: pointer;
 }
<script src = "https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id = "root"></div>

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

Jared Smith 03.05.2019 13:22

Любая другая информация, которую вы читали о стрелочных функциях, обычных именованных функциях и анонимных функциях, объявленных с переменными, по-прежнему применима здесь. Разницы в производительности нет между ними. И даже невозможно определить, является ли функция стрелочной функцией во время выполнения, поэтому React не может и не может обрабатывать их иначе, чем обычные функции.

Khauri 03.05.2019 13:24

Согласно предыдущему комментарию см. это и это.

Jared Smith 03.05.2019 13:26

Уф. Я ошибался, говоря, что не могу обнаружить функции стрелок. stackoverflow.com/questions/28222228/…, но я очень сомневаюсь, что React так делает. В основном из-за транспиляторов.

Khauri 03.05.2019 13:40

См. также stackoverflow.com/a/55784719/3731501

Estus Flask 03.05.2019 14:03
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
9
5
1 931
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

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

React действительно не заботится о том, какой из них вы используете (и не может его обнаружить).

const A = () => {
  const name = getName();
  
  function getName() {
    return 'praffn';
  }
  
  // Will not work
  // const getName = () => 'praffn';
  
  return <p>Hi, {name}</p>;
}

ReactDOM.render(<A/>, document.getElementById('root'));
<script src = "https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id = "root"></div>

Лично я не обнаружил, что поднятие функций представляет большую проблему на практике (в отличие от подъема var), и я думаю, что наличие ключевого слова function делает код более читаемым, чем если бы почти все начиналось с const. (Я подозреваю, что Facebook может иметь аналогичные причины для использования function в своих примерах.) Но, как уже указал Филипп, это стилистическое предпочтение — любой из них будет работать нормально.

Matt Browne 03.05.2019 13:35

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

Phillip 03.05.2019 13:38

@MattBrowne Я думаю, что ключевое слово function также делает код более читабельным. И я почти никогда не использую подъемную "функцию".

cbdeveloper 03.05.2019 13:41

Поскольку вы не обращаетесь к контексту this, оба будут вести себя как тоже самое.

Чтобы понять больше, вы можете проверить, как Babel транслируется в ECMA:

 const handleClick2 = () => {
    console.info('handleClick2 executed...');
    this.x=3
 }

будет транспилирован как:

"use strict";

var _this = void 0;

var handleClick2 = function handleClick2() {
  console.info('handleClick2 executed...');
  _this.x = 3;
};

Ссылка на блокнот Babel

Доступ к this внутри стрелочной функции или объявления функции не даст никакой разницы, поскольку this будет равно undefined. Это потому что React components are written within ES6 modules, which automatically run in strict mode.

Ani Naslyan 09.11.2021 18:50

Другие вопросы по теме