Знаете ли вы, что существует четыре способа создания функции в JavaScript? Да, вы правильно прочитали, четыре способа. Если вы какое-то время работали с JavaScript, вы, вероятно, видели все эти подходы и задавались вопросом, есть ли какая-то логика в выборе определенного способа определения функции в JavaScript. В этой статье я пролью больше света на эту тему.

Ранее я упоминал, что существует четыре способа определения функций в JavaScript: объявление функции, функциональные выражения, стрелочные функции и конструкторы функций. Давайте рассмотрим их все и попробуем выяснить их плюсы и минусы.

1. Объявление функции

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

// function declaration
function convertMetersToMiles(meters) {
  return meters * 0.00062137;
}

let result = convertMetersToMiles(1000);

Чтобы определить функцию с помощью этого подхода, вы должны начать использовать ключевое слово «функция». Затем вы вводите название функции, в данном случае convertMetersToMiles. Если у вас есть какие-либо параметры, которые необходимо указать, вы можете передать их в круглых скобках. В этом примере только один. После этого идет тело, заключенное в фигурные скобки. Он содержит логику функции. Этот способ объявления функции часто используется, потому что он очень похож на то, как вы определяете функции в других языках программирования.

Подъем

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

// will work just fine and print 0.62137
console.log(convertMetersToMiles(1000));

function convertMetersToMiles(meters) {
  return meters * 0.00062137;
}

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

2. Выражение функции

Другой способ определить функции в JavaScript — использовать функциональное выражение.

const convertMetersToMiles = function (meters) {
  return meters * 0.00062137;
}

console.log(convertMetersToMiles(1000));

Вы можете понять, почему этот стиль называется функциональным выражением. Мы присваиваем функцию переменной. В данном случае мы назначаем функцию преобразования переменной с именем convertMetersToMiles. Это не относится к объявлениям функций. Там мы создаем функцию, и присваивание не требуется.

В большинстве случаев функция, определенная таким образом, является анонимной. После ключевого слова функция нет имени. Итак, как мы вызываем его? Вот тут и приходит на помощь переменная. Мы можем использовать переменную для выполнения функции. В нашем примере для получения результата мы вызываем convertMetersToMiles, передавая 1000 в качестве аргумента.

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

// Error ->  Cannot access 'convertMetersToMiles' before initialization
console.log(convertMetersToMiles(1000));

const convertMetersToMiles = function (meters) {
  return meters * 0.00062137;
}

3. Функция стрелки

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

const convertMetersToMiles = (meters) => meters * 0.00062137;

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

const convertMetersToMiles = (meters) => {
  return meters * 0.00062137;
}

Стрелочные функции отлично подходят для устранения лишнего кода или передачи обратного вызова. Однако у них есть некоторые ограничения:

  • Стрелочные функции не имеют собственной привязки «this», поэтому их не следует использовать в качестве методов или для обработки событий браузера.
  • Вы не можете получить доступ к объекту arguments внутри стрелочной функции.
  • Стрелочные функции нельзя использовать в качестве функций-конструкторов.

Давайте посмотрим пример.

const converter = {
  metersToMilesConstant: 0.00062137,
  convertMetersToMiles: (meters) => meters * this.metersToMilesConstant,
};

// will return NaN because this referes to the Window/Global object
console.log(converter.convertMetersToMiles(1000));

4. Конструктор функций

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

const convertMetersToMiles = new Function(
  'meters',
  'return meters * 0.00062137;'
);

console.log(convertMetersToMiles(1000));

Чтобы создать объект функции, я передаю параметры, в данном случае параметр с именем «meters» и тело в виде строки. Я знаю, это выглядит странно, но это работает.

Почему, во имя Бога, я должен использовать такой странный способ создания функции? Ты

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

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

Итак, как лучше всего создать функцию в JavaScript?

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

Вы можете выбрать стрелочные функции для простых функций или для передачи анонимных функций в качестве обратных вызовов. Это устранит шаблонный код и упростит чтение вашей кодовой базы. В противном случае вы можете использовать комбинацию функциональных выражений и объявлений функций. Просто помните о подъеме.