Введение в функциональное программирование на javascript

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

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

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

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

Императивный JavaScript

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

Не смотря на то, что разработчики приложив все возможные усилия старались сопоставить гибкость JavaScript со сложностью объектной модели документа браузера(DOM), фактический код JavaScript довольно часто смотрелся чем-то наподобие:

var resu function getText() { var someText = prompt(Give me something to capitalize); capWords(someText); alert(result.join( )); }; function capWords(input) { var counter; var inputArray = input.split( ); var transformed = ; result = []; for (counter = 0; counterinputArray.length; counter++) { transformed = [ inputArray[counter].charAt(0).toUpperCase(), inputArray[counter].substring(1) ].join(); result.push(transformed); } }; document.getElementById(main_button).onclick = getText;

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

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

Императивный код, так же как данный запрос, написан, дабы быть прочтённым и выполняется сверху вниз (плюс-минус мало поднятия переменных). Но имеется пара улучшений, каковые мы можем внести, дабы сделать его более читабельным и чистым, всего лишь воспользовавшись объектно-ориентированной природой JavaScript.

Объектно-ориентированный JavaScript

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

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

(function() { use strict; var SomeText = function(text) { this.text = text; }; SomeText.prototype.capify = function(str) { var firstLetter = str.charAt(0); var remainder = str.substring(1); return [firstLetter.toUpperCase(), remainder].join(); }; SomeText.prototype.capifyWords = function() { var result = []; var textArray = this.text.split( ); for (var counter = 0; countertextArray.length; counter++) { result.push(this.capify(textArray[counter])); } return result.join( ); }; document.getElementById(main_button).addEventListener(click, function(e) { var something = prompt(Give me something to capitalize); var newText = new SomeText(something); alert(newText.capifyWords()); }); }());

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

В том месте кроме того имеется директива строгого применения, чтобы возможно было воспользоваться последним движком JavaScript, а старомодный способ OnClick заменен новым addEventListener, по причине того, что, кто сейчас в здравом уме применяет версию IE8 либо более ранние предположения? Скрипт, подобный этому, возможно будет засунут в конце элементав HTML-документе, дабы убедиться, что вся DOM загружена, перед тем как указанный скрипт будет обработан, так что , к которой он относится, будет дешева.

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

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

Функциональный JavaScript

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

(function() { use strict; var capify = function(str) { return [str.charAt(0).toUpperCase(), str.substring(1)].join(); }; var processWords = function(fn, str) { return str.split( ).map(fn).join( ); }; document.getElementById(main_button).addEventListener(click, function(e) { var something = prompt(Give me something to capitalize); alert(processWords(capify, something)); }); }());

Вы увидели, как меньше эта версия? Мы задали лишь две функции: capify и processWords. Любая из этих функций чистая, это значит, что они , это указывает, что они не зависят от собственного положения в коде, из которого они вызываются. . Функции не создают побочные эффекты, каковые изменяют переменные. Существует только один итог, возврата функции для любого комплекта доводов.

Из-за совершённых улучшений, новые функции весьма легко протестировать, они также будут быть легко вырезаны из кода, и использованы в любом втором месте без каких-либо дополнительных модификаций.

Вероятно тут имеется лишь одно главное слово, которое вы имели возможность не знать, в случае если до этого не сталкивались с функциональным кодом. Мы воспользовались новым способом map в Array, чтобы применить функцию к каждому элементу временного массива, что мы создали, в то время, когда поделили отечественную строчок. Map есть только одним из немногих эргономичных способов, показавшихся в следствие того, что серверный интерпретатор и современные браузеры JavaScript внедрили стандарты ECMAscript 5. Примените map, на месте цикла for, убрав переменную counter, и ваш код станет намного чище и читабельнее.

Начните мыслить функционально

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

  • Зависят ли мои функции от контекста, в котором они вызываются, либо они чистые и свободные?
  • Могу ли я написать эти функции так, дабы они постоянно возвращали одинаковый итог для заданных входных данных?
  • Уверен ли я, что мои функции не изменяют ничего лишнего?
  • Если бы я желал применять эти функции в второй программе, мне необходимо было бы внести трансформации в них?

Высоких конверсий!

Случайные статьи:

Вебинар «Функциональное программирование на JavaScript»


Подборка похожих статей:

riasevastopol