Vitamin – сервис для выгодного управления вашей рекламой
  • Все популярные рекламные сети в одном окне
  • Агентское вознаграждение до 16% на личный счет или рекламу
  • Любые дополнительные услуги под ваши потребности
  • Бесплатное обучение маркетингу
  1. Главная >
  2. Блог >
  3. Введение в функциональное программирование на JavaScript

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

1

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

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

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

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

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

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

var result;
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; counter < inputArray.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 документе, который определяет <button id=”main_button”> вы скорее всего получите запрос на текст, который можно редактировать, а затем увидите, что указанный запрос, содержит в себе слова, каждое из которых начинается с заглавной буквы.

Императивный код, так же как этот запрос, написан, чтобы быть прочитанным и выполняется сверху вниз (плюс-минус немного поднятия переменных). Однако есть несколько улучшений, которые мы можем внести, чтобы сделать его более читабельным и чистым, всего лишь воспользовавшись объектно-ориентированной природой 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; counter &lt; textArray.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 или более ранние версии? Скрипт, подобный этому, вероятно будет вставлен в конце элемента <BODY> в HTML-документе, чтобы убедиться, что вся DOM загружена, прежде чем указанный скрипт будет обработан, так что <button>, к которой он относится, будет доступна.

Но, несмотря на все реконфигурации, остается много рабочих продуктов императивного стиля, которые привели нас сюда. Методы в функции конструктора зависят от переменных, область видимости которых распространяется вплоть до родительского объекта. Там есть циклические конструкции для перебора элементов массива, состоящего из строк. Так же есть переменная 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 функционально, если в следующий раз, когда будете писать в нем программу задатие себе следующие вопросы:

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

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

blog comments powered by Disqus
Vitamin – сервис для выгодного управления вашей рекламой
  • Все популярные рекламные сети в одном окне
  • Агентское вознаграждение до 16% на личный счет или рекламу
  • Любые дополнительные услуги под ваши потребности
  • Бесплатное обучение маркетингу
copyright © 2011–2024 Все права защищены
Запрещено любое копирование материалов ресурса без письменного согласия владельца — ООО "Феникс-Маркетинг". ИНН:7725812838, КПП:772501001, ОГРН: 513774619323915280, Москва, ул. Ленинская слобода, д. 19, стр. 1, этаж/пом 3/25

Генеральный партнёр: STRATE FZ-LLC License number 47005249 Address: B03-227 Business Center 02 RAKEZ Business Zone-FZ RAK (Ras Al Khaimah), United Arab Emirates Email: corporate@strate.ae