В книге « Секреты ниндзя JavaScript » Джона Резига и Беар Бибо авторы описывают функции как наиболее важную концепцию языка, потому что в JavaScript все вращается вокруг них. Функции действительно очень важны. Новая версия JavaScript добавляет к ним еще больше функций, которые вы полюбите использовать. В этом руководстве вы узнаете больше о новых функциях, которые работают с функциями и которые позволят вам написать еще более мощный код.
Если вы хотите узнать больше о ECMAScript 6, я предлагаю вам ознакомиться с моими статьями о типах данных String
и Array
, а также о новых представленных WeakMap
данных Map
и WeakMap
.
Стрелка Функции
Первая функция, которую я хочу охватить, — это функция стрелки. Как следует из названия, для его использования мы будем использовать стрелку ( =>
), которую вы можете распознать, если когда-либо работали с PHP. Эта функция поставляется в двух формах, которые интегрируются с текущим синтаксисом функции. Имейте в виду, что с помощью функции со стрелкой вы можете заменить только анонимные функции. Два возможных синтаксиса показаны ниже:
// First syntax ([param] [, param]) => { statements } // Second syntax param => expression
Заполнитель параметра представляет параметры функции, а statements
представляют тело функции. expression
представляет любое допустимое выражение и заменяет правую часть первого синтаксиса ( { statements }
). В первой форме вы можете поместить любое количество параметров в круглые скобки, в то время как вторая ограничена одним.
Чтобы понять, как они выглядят, скажем, у нас есть набор чисел, который нам нужно проверить на четность или нечетность. Кроме того, нам нужно выполнить этот тест только один раз, поэтому нам не нужно определять функцию isEven()
и мы можем использовать анонимную функцию. Наша функция вернет true
если число четное, и false
противном случае. Это приводит к коду ниже:
var numbers = [10, 21, 15, 8]; // prints "[true, false, false, true]" console.log( numbers.map(function(number) { return number % 2 === 0; }) );
Это прекрасный пример того, почему функции стрелок полезны. Как видите, анонимная функция довольно проста, и ее тело состоит из одного оператора. Тем не менее, чтобы придерживаться текущего синтаксиса JavaScript, мы должны ввести много дополнительных символов. Благодаря функциям стрелок мы можем избежать их и написать код следующим образом:
var numbers = [10, 21, 15, 8]; // prints "[true, false, false, true]" console.log( numbers.map(number => number % 2 === 0) );
Короче не так ли? В этом случае мы можем использовать второй, более короткий синтаксис, потому что тело функции состоит только из одного оператора. Кроме того, единственное заявление, которое мы получили, — это return
. Фактически, со вторым синтаксисом результат правильного выражения используется как возвращаемое значение.
Если мы хотим использовать функции со стрелками для замены функций на большее количество операторов, мы можем использовать первую форму. Чтобы увидеть его в действии, давайте расширим нашу функцию, чтобы убедиться, что данный параметр на самом деле является числом и является целым числом. Полученный код выглядит следующим образом:
var numbers = [10, 15, false, 'test', {}]; // prints "[true, false, false, false, false]" console.log( numbers.map(function(number) { // The parameter is a number and it's an integer if (typeof number !== 'number' || number % 1 !== 0) { return false; } return number % 2 === 0; }) );
Мы можем сделать его короче, используя первую форму функций стрелок, как показано ниже:
var numbers = [10, 15, false, 'test', {}]; // prints "[true, false, false, false, false]" console.log( numbers.map(number => { // The parameter is a number and it's an integer if (typeof number !== 'number' || number % 1 !== 0) { return false; } return number % 2 === 0; }) );
Демонстрационная версия предыдущего кода показана ниже и также доступна в виде JSFiddle .
Функции стрелок не только хороши, потому что они позволяют нам сохранить несколько нажатий клавиш. Другая важная особенность заключается в том, что они неявно связывают значение this
с функцией. Представьте, что на данной странице есть несколько кнопок и что на странице есть следующий код:
var Utility = { fullname: , handler: function (elements) { for (var i = 0; i < elements.length; i++) { elements[i].addEventListener('click', function() { console.log(this.fullname); }); } } }; var buttons = document.getElementsByTagName('button'); Utility.handler(buttons);
Однако, когда обработчик присоединен for
циклу for
, значение this
больше не будет объектом Utility
, а будет window
. Следовательно, консоль будет отображаться как undefined
.
Это распространенная проблема в JavaScript, которую мы можем решить разными способами. Например, вы можете сохранить ссылку на объект Utility
с помощью переменной (классическая переменная var that = this
подход) или использовать функцию bind()
. Однако, благодаря введению функции стрелки, мы можем решить эту проблему следующим образом:
var Utility = { fullname: , handler: function (elements) { for (var i = 0; i < elements.length; i++) { elements[i].addEventListener('click', () => { console.log(this.fullname); }); } } }; var buttons = document.getElementsByTagName('button'); Utility.handler(buttons);
Демонстрационная версия предыдущего кода показана ниже и также доступна как JSFiddle .
Эта функция в настоящее время поддерживается только Firefox 22+.
Значения по умолчанию для параметров
В новой версии JavaScript появилась еще одна особенность, которую разработчики PHP широко используют: возможность устанавливать значения по умолчанию для параметров. Версия JavaScript даже более мощная, чем версия PHP, потому что значение по умолчанию, используемое для данного параметра, доступно для следующих параметров в списке. Кроме того, в JavaScript за параметрами со значениями по умолчанию могут следовать параметры без. В PHP это невозможно. Чтобы назначить значение по умолчанию, вы должны поставить знак равенства сразу после имени параметра, за которым следует значение по умолчанию, которое вы хотите назначить, как вы сделали бы в классическом назначении.
Значения по умолчанию — это то, что мы использовали несколько раз в прошлом, но другим способом. Обдумайте следующий код:
function Person(name, surname, gender) {
Выполнение этого фрагмента кода работает, как и ожидалось, но ручное управление значениями по умолчанию очень скучно. Кроме того, используемый подход может иметь неожиданные результаты, поскольку он проверяет ложное значение, а затем назначает значение по умолчанию. Допустим, один из параметров был числом, и идеальным значением по умолчанию является 10, но ноль приемлем. Используя технику кода выше, мы могли бы написать:
param = param || 10;
В этом случае, поскольку ноль является ложным значением, 10 будет присвоено param
который на самом деле не то, что мы хотим. Конечно, можно использовать другие методы, но они требуют от нас писать еще больше кода. Благодаря новым возможностям ECMAScript 6 мы можем избежать подобных проблем и сократить код, как показано ниже:
function Person(name = 'Aurelio', surname = 'De Rosa', gender = 'male') { this.toString = function() { return 'My name is ' + name + ' ' + surname + ' and I am a ' + gender; } };
Эта версия не только более краткая, но и более удобочитаемая, поскольку значения по умолчанию установлены близко к параметрам. Стоит отметить, что значение по умолчанию используется также, если переданный аргумент не undefined
.
Демонстрационная версия предыдущего кода показана ниже и также доступна в виде JSFiddle .
В предыдущем примере мы видели только основное использование этой новой функции. Следующий пример показывает, как мы можем иметь параметры без значения по умолчанию после того, которое имеет значение по умолчанию:
function prod(number1 = 1, number2) { return number1 * number2; }
В последнем примере показан параметр, значение по умолчанию которого зависит от предыдущего параметра со значением по умолчанию:
function Person(name, surname, username = name + ' ' + surname) { }
Как и предыдущая функция, это значение по умолчанию для параметра в настоящее время поддерживается только Firefox 15+.
Параметр покоя
Параметр rest — это специальный параметр, который позволяет нам выразить произвольное количество параметров в функции. Он будет включать в себя все переданные аргументы, которые не соответствуют именованному параметру, как элементы массива (поэтому не похожий на массив элемент). Чтобы определить этот параметр, вы должны поместить его как последний в сигнатуре функции и добавить к нему три точки. Синтаксис этого параметра представлен ниже:
function (...paramName) { }
paramName
может быть любым произвольным именем, которое вы хотите назначить этому специальному параметру.
Разработчики долгое время моделировали эту функцию, используя arguments
и удаляя названные параметры. Чтобы визуализировать разницу между старым подходом и новым, предположим, что у нас есть функция, которая принимает некоторые данные о человеке и печатает их на консоли. Эта функция имеет два обязательных параметра, которые представляют имя и фамилию человека, а затем любое количество дополнительных параметров. В старом подходе такую функцию можно записать следующим образом:
function presentation(name, surname) { var otherInfo = [].slice.call(arguments, 2); console.log('My name is ' + name + ' ' + surname); if (otherInfo.length > 0) { console.log('Other info: ' + otherInfo.join(', ')); } }
Используя параметр rest, мы можем избавиться от первого оператора функции, приведшего к приведенному ниже коду:
function presentation(name, surname, ...otherInfo) { console.log('My name is ' + name + ' ' + surname); if (otherInfo.length > 0) { console.log('Other info: ' + otherInfo.join(', ')); } }
Демонстрационная версия предыдущего кода показана ниже и также доступна в виде JSFiddle .
Эта функция в настоящее время поддерживается только Firefox 15+.
Вывод
В этом руководстве мы рассмотрели новые функции, представленные в ECMAScript 6, которые работают с функциями. Они позволят нам написать еще более мощный и лаконичный код. Из-за слабой поддержки браузеров они не являются чем-то, что вы действительно можете использовать сегодня, но вы должны быть готовы, потому что именно так будет выглядеть будущее JavaScript.