Самая ожидаемая функция в современном JS — это стрелочные функции, использующие=>
идентифицировать. Стрелочные функции имеют два основных преимущества: во-первых, очень лаконичный синтаксис, во-вторых, интуитивно понятная область действия иthis
привязка.
Из-за этих преимуществ стрелочные функции предпочтительнее других форм объявления функций. Например, популярныеairbnb eslint configuration库
Заставляет использовать стрелочные функции JavaScript для создания анонимных функций.
Однако, как и все остальное в мире, стрелочные функции имеют некоторые преимущества и некоторые «недостатки», которые требуют некоторых компромиссов при их использовании.
Научиться находить компромиссы — это ключ к использованию хороших стрелочных функций. В этом посте мы рассмотрим, как работают стрелочные функции, а затем углубимся в то, как стрелочные функции могут улучшить наш код в реальном коде, а также в некоторых ситуациях, когда стрелочные функции использовать не рекомендуется.
Что такое стрелочная функция
Стрелочные функции в JS, вероятно, такие же, как в python.lambda(python定义匿名函数的关键字)
и в рубинеblocks(类似于闭包)
Такой же.
Эти анонимные функции имеют свой особый синтаксис: они сначала получают определенное количество аргументов, а затем выполняются в области действия определяющей их функции или ближайшей области видимости.
Мы обсудим это подробно далее.
Синтаксис стрелочных функций
Стрелочные функции имеют общую структуру, но есть и много частных случаев, которые можно упростить. Основная структура выглядит следующим образом:
(argument1, argument2, ... argumentN) => {
// function body
}
Внутри круглых скобок находится ряд параметров, за которыми следует символ стрелки.=>
и, наконец, тело функции. Это очень похоже на традиционную функцию, только мы ее опускаемfunction
ключевое слово и добавил=>
после параметра.
Кроме того, здесь есть много ситуаций, которые делают структуру стрелочной функции более лаконичной.
Во-первых, если тело функции представляет собой одно выражение, вы можете опустить фигурные скобки и написать выражение в одной строке, и результат выражения будет возвращен непосредственно функцией. Например:
const add = (a, b) => a + b;
Во-вторых, если это передается как один параметр, вы также можете опустить круглые скобки в части параметра. Например:
const getFirst = array => array[0];
Как видите, это выглядит намного лаконичнее, и мы опишем больше функций позже.
Продвинутая грамматика
Будет очень полезно, если вы поймете эти сложные синтаксисы.
Во-первых, если вы пытаетесь написать функцию в одну строку, но возвращаемое значение является содержимым объекта, вы хотели бы написать:
(name, description) => {name: name, description: description};
Проблема в том, что такой синтаксис может привести к двусмысленности, ошибочно приняв вас за написание тела функции. Если вы хотите вернуть один объект, заключите его в круглые скобки:
(name, description) => ({name: name, description: description});
объемлющая область контекста
В отличие от других форм функций, стрелочные функции не имеют собственного контекста выполнения. На практике это означает, что в кодеthis
а такжеarguments
Оба наследуют от своих родительских функций.
Например, сравните разницу между функцией стрелки и традиционной функцией:
const test = {
name: 'test object',
createAnonFunction: function() {
return function() {
console.log(this.name);
console.log(arguments);
};
},
createArrowFunction: function() {
return () => {
console.log(this.name);
console.log(arguments);
};
}
};
У нас есть объект с двумя методами, каждый из которых возвращает анонимную функцию. Разница в том, что в первом методе используются традиционные выражения функций, а во втором — выражения функций стрелок. Если мы запустим с одинаковыми параметрами, мы получим два разных результата.
const anon = test.createAnonFunction('hello', 'world');
//返回匿名函数
const arrow = test.createArrowFunction('hello', 'world');
anon();
//undefined
//{}
// this->window
arrow();
//test object
//object { '0': 'hello', '1': 'world' }
//this->test
Первая анонимная функция имеет свой собственный контекст (указывающий не на тестовый объект), без ссылки при ее вызове.this.name
свойства, (примечание: сейчасthis
направлениеwindow
), и никаких аргументов для вызова при его создании. С другой стороны, стрелочная функция имеет тот же контекст, что и создавшая ее функция, что дает ей доступ к аргументам и объектам.
Стрелочные функции улучшают ваш код
Традицияlambda
Одним из основных вариантов использования функций является использование функций для обхода массивов, что теперь реализовано с помощью стрелочных функций JavaScript.
Скажем, у вас есть массив со значениями, и вы хотите перейти кmap
Настоятельно рекомендуется перебирать каждый элемент с помощью стрелочных функций:
const words = ['hello', 'WORLD', 'Whatever'];
const downcasedWords = words.map(word => word.toLowerCase());
Очень распространенный пример — возврат некоторого значения объекта:
const names = objects.map(object => object.name);
Аналогично, при использованииforEach
заменить традиционныеfor
При зацикливании функция стрелки на самом деле интуитивно понятна, чтобы сохранитьthis
с родительского уровня
this.examples.forEach(example => {
this.runExample(example);
});
Обещания и цепочки обещаний
Стрелочные функции также делают код более интуитивно понятным и лаконичным при написании асинхронных программ.
Промисы упрощают написание асинхронных программ. Хотя вы с удовольствием используетеasync/await
, тоже надо пониматьpromise
, потому что это их основа.
С промисами вам все равно нужно определить функцию обратного вызова после того, как ваш код завершит выполнение. Это идеальное место для стрелочных функций, особенно если вы создаете функции с состоянием и хотите в то же время ссылаться на что-то в объекте.
this.doSomethingAsync().then((result) => {
this.storeResult(result);
});
преобразование объекта
Другое распространенное и очень полезное место для стрелочных функций — преобразование инкапсулированных объектов.
Например, в Vue.js есть общий шаблон, который заключается в использованииmapState
Включайте части хранилища Vuex непосредственно в компоненты Vue.
Это включает в себя определение набораmappers
, используемый для преобразования исходного объекта в полный вывод, что действительно необходимо при проблемах с компонентами.
Для этой серии простых преобразований наиболее подходящими являются стрелочные функции. Например:
export default {
computed: {
...mapState({
results: state => state.results,
users: state => state.users,
});
}
}
Сценарии, в которых не следует использовать стрелочные функции
Есть много сценариев, в которых не рекомендуются стрелочные функции, которые не только бесполезны, но и вызывают ненужные проблемы.
Во-первых, это методы объекта. Вот пример контекста функции, который полезен для нашего понимания.
Раньше была тенденция использоватьclass
Синтаксис класса и стрелочные функции, для которых автоматически связываются методы. Например: метод события может быть использован, но все еще привязан к классу class.
Это выглядит следующим образом:
class Counter {
counter = 0;
handleClick = () => {
this.counter++;
}
}
В этом методе, если он вызывается функцией события клика, он неCounter
В контексте , он все еще может получить доступ к данным экземпляра, недостатки этого метода очевидны.
Он предоставляет возможность быстрого связывания функций таким образом, но функции могут быть выражены в различных формах и довольно неинтуитивны. Если вы попытаетесь использовать такой объект в прототипе, это будет плохо для тестирования и вызовет много проблем. Вместо этого рекомендуется использовать обычную привязку, если это необходимо в конструкторе экземпляра:
class Counter {
counter = 0;
handleClick() {
this.counter++;
}
constructor() {
this.handleClick = this.handleClick.bind(this);
}
}
глубокий звонок
Еще одна область, где использование стрелочных функций может доставить вам головную боль, — это когда вы используете комбинацию многих функций, особенно глубоких функций. Простые причины Как и анонимные функции, трассировка стека сложна.
Это не проблема, если ваша функция находится всего на один уровень ниже, а не выполняет глубокую итерацию. Но если вы определите функции как стрелочные функции и вызовете между ними туда и обратно, вы будете сбиты с толку кодом при отладке ошибки или даже получите следующее сообщение об ошибке:
{anonymous}()
{anonymous}()
{anonymous}()
{anonymous}()
{anonymous}()
//anonymous 匿名
функция с динамическим контекстом
Существует также одна из самых запутанных ситуаций, когда функции стрелок могут вас сбить с толку.this
Пришло время для динамического связывания.
Если вы используете стрелочные функции в следующих ситуациях, динамическая привязка this не будет работать должным образом, и вы будете сбиты с толку тем, почему код не работает должным образом, и создаст проблемы для людей, с которыми вы будете работать позже.
Некоторые типичные примеры:
- Вызывающая функция события, это указывает на текущее целевое свойство
- В jquery большую часть времени это указывает на текущий выбранный элемент
- во вью,
methods
а такжеcomputed
серединаthis
Указывает на компонент vue.
Конечно, вы также можете осторожно использовать стрелочные функции в приведенной выше ситуации. но особенно вjquery
а такжеvue
, это часто мешает нормальной работе и сбивает с толку, почему код, который выглядит так же, как чужой код, просто не работает.
Суммировать
Стрелочные функции — это особое свойство языка JS, которое во многих случаях делает код более непредсказуемым. Тем не менее, как и другие функции языка, они имеют свои преимущества и недостатки. Поэтому мы должны использовать его только как инструмент, а не просто заменять все это стрелочными функциями.
Эта статья является просто переводом для личного интереса, если есть какие-то ошибки, надеюсь, вы сможете их исправить. Авторские права на статью принадлежат оригинальному автору.
Оригинальный адрес:взрыв со.IO/JavaScript-…