Первый раз я столкнулся с функциональным программированием когда работал в Xiaomi.Тогда я читал разные композиционные коды, написанные начальником до этого, а потом какие-то инструментальные функции ramda.Это выглядело очень сложно, и тогда я попробовал я изо всех сил жалуюсь на функциональное программирование. Теперь я оглядываюсь на него. В то время я был очень недальновидным и просто хотел сказать: «Это действительно ароматно».
Я недавно изучал функциональное программирование, и я действительно чувствую, что мое мышление значительно улучшилось в процессе обучения, и мои способности к абстракции значительно улучшились, что заставило меня глубоко почувствовать прелесть функционального программирования. Поэтому я планирую использовать от 5 до 8 статей позже, чтобы подробно представить идею функционального программирования, основы, как проектировать, тестировать и т. д.
Сегодняшняя статья в основном знакомит с идеей функционального программирования.
- Работает ли функциональное программирование?
- Что такое функциональное программирование?
- Преимущества функционального программирования.
Объектно-ориентированное программирование (ООП) упрощает понимание кода за счет инкапсуляции изменений. Функциональное программирование (FP) упрощает понимание кода за счет минимизации изменений. -- Майкл Фезерс (Twitter)
Как мы все знаем, JavaScript — это динамический язык с большим количеством общих состояний, и со временем код становится настолько сложным, что становится громоздким и трудным в обслуживании. Объектно-ориентированный дизайн может помочь нам решить эту проблему в определенной степени, но этого недостаточно.
Поскольку состояний много, особенно важно обрабатывать поток данных и передачу изменений.Не знаю, знаете ли выреактивное программированиеПолезна ли эта парадигма программирования для работы с асинхронным ответом JavaScript или ответом на событие. В заключение, когда мы разрабатываем приложение, мы должны учитывать, соблюдаются ли следующие принципы проектирования.
- Расширяемость. Нужно ли мне постоянно реорганизовывать код для поддержки дополнительных функций?
- Простая модульность — если я изменю один файл, повлияет ли это на другой?
- Возможность повторного использования — много ли дублированного кода?
- Тестируемость. Беспокоит ли меня добавление модульных тестов к этим функциям?
- Разумный. Является ли код, который я пишу, сильно неструктурированным и трудным для понимания?
Я могу сказать вам это, как только вы изучите функциональное программирование, эти проблемы будут легко решены.Изначально идея была в функциональном программировании.Как только вы освоите функциональное программирование, а затем изучите реактивное программирование, понять его будет легче.Я испытал это на себе. сам. Когда я раньше изучал Rxjs, это было очень болезненно.Честно говоря, Rxjs — самая сложная библиотека, которую я когда-либо изучал, без исключения. После мучительного месяца или двух некоторые вещи все еще не работают вместе, что я считаю само собой разумеющимся, пока недавно не изучил функциональное программирование. Без преувеличения, я постараюсь познакомить вас с Rxjs в следующих статьях, я также поделился этой темой с компанией.
Что такое функциональное программирование?
Проще говоря, функциональное программирование — это стиль разработки программного обеспечения, в котором особое внимание уделяется использованию функций. Когда вы видите это предложение, я думаю, вы все еще в замешательстве. Вы не знаете, что такое функциональное программирование. Не волнуйтесь, я думаю, вы поймете, когда увидите его.
Еще одна вещь, которую следует иметь в виду, это то, что целью функционального программирования является использование функций дляАбстрактный поток управления и операции над данными, так что в системеустранить побочные эффектыиМинимизируйте изменения состояния.
Кратко продемонстрируем всю прелесть функционального программирования на примере.
Текущим требованием является вывод вывода на веб-страницу.“Hello World”.
Может быть, новичок так и написал бы.
document.querySelector('#msg').innerHTML = '<h1>Hello World</h1>'
Эта программа очень проста, но весь код мертв и не может быть использован повторно.Если вы хотите изменить формат, содержание и т. д. сообщения, вам нужно переписать все выражение, чтобы его могли написать опытные фронтмены. конечные разработчики.
function printMessage(elementId, format, message) {
document.querySelector(elementId).innerHTML = `<${format}>${message}</${format}>`
}
printMessage('msg', 'h1', 'Hello World')
Это немного улучшает, но это все еще не повторно используемый фрагмент кода, если я пишу текст в файл, а не не-HTML, или я хочу повторить отображениеHello World.
Итак, как бы вы написали этот код как функциональный разработчик?
const printMessage = compose(addToDom('msg'), h1, echo)
printMessage('Hello World')
Объясните этот код, гдеh1иechoфункции,addToDomТакже очевидно, что это функция, так почему же мы пишем ее именно так? Похоже, что функций гораздо больше.
На самом деле речь идет о разложении программы на более повторно используемые, более надежные и простые для понимания части, а затем их объединении в более разумную программу в целом, что является основным принципом, о котором мы говорили ранее.
Compose кратко объясните, что он будет выполнять функцию последовательно от последнего параметра к первому параметру.Каждый параметр compose является функцией.Если вы не понимаете, вы можете проверить это.Это суть промежуточной части редукции.
Можно видеть, что мы являемся функцией разделения задачи на несколько мельчайших частиц, а затем выполнения нашей задачи путем ее объединения, что очень похоже на нашу идею компонентизации, разбивая всю страницу на несколько компонентов, а затем собирая ее для завершения. вся наша страница. В функциональном программировании композиция — очень, очень, очень важная идея.
Хорошо, давайте снова изменим требование, теперь нам нужно повторить текст три раза и вывести его в консоль.
var printMessaage = compose(console.log, repeat(3), echo)
printMessage(‘Hello World’)
Видно, что мы изменили требования и не изменили внутреннюю логику, а просто реорганизовали функцию.
Вы можете видеть, что функциональное программирование имеет декларативный паттерн в разработке. Чтобы полностью понять функциональное программирование, давайте сначала рассмотрим несколько основных концепций.
- декларативное программирование
- чистая функция
- Прозрачность котировок
- неизменность
декларативное программирование
Функциональное программирование — это парадигма декларативного программирования: эта парадигмаописать ряд операций, но нетпоказать, как они реализованыиликак потоки данных передают их.
Известный SQL-оператор — очень типичный пример декларативного программирования, состоящий из одного за другимописыватьКакая композиция утверждений должна быть в результате запроса, и реализован внутренний механизм извлечения данныхАннотация.
Давайте посмотрим на другой набор кода и сравним императивное программирование с декларативным.
// 命令式方式
var array = [0, 1, 2, 3]
for(let i = 0; i < array.length; i++) {
array[i] = Math.pow(array[i], 2)
}
array; // [0, 1, 4, 9]
// 声明式方式
[0, 1, 2, 3].map(num => Math.pow(num, 2))
Вы можете видеть, что императивы сообщают компьютеру, как именно выполнять определенную задачу.
И декларативность программыописание и оценкаотдельный. Он фокусируется на том, как использовать различныевыражениедля описания логики программы без обязательного указания изменений в ее потоке управления или отношениях состояний.
Почему мы хотим избавиться от циклов кода? Циклы являются важной структурой управления командами, но их трудно повторно использовать и вставлять в другие операции. Функциональное программирование, с другой стороны, направлено на то, чтобы максимально улучшить безгражданство и неизменность кода. Для этого научитесь использоватьНет побочных эффектовфункция, также называемая чистой функцией
чистая функция
чистая функцияникаких побочных эффектовФункция. Тот же вход имеет тот же результат, как и функция, которую мы ходили в школу.
Часто эти условия имеют побочные эффекты.
- Изменить глобальную переменную, свойство или структуру данных
- Изменить исходное значение параметра функции
- Обработка пользовательского ввода
- бросить исключение
- трафаретная печать или журнал
- Запрашивайте HTML-документы, файлы cookie браузера или получайте доступ к базам данных
Возьмем простой пример
var counter = 0
function increment() {
return ++counter;
}
Эта функция нечиста. Она считывает внешние переменные. Вы можете подумать, что в этом коде нет проблем, но нам нужно знать, что такие расчеты, основанные на внешних переменных, трудно предсказать. Вы также можете быть в другом Значение счетчика где-то изменен, так что значение, которое вы увеличиваете, не соответствует ожидаемому.
Чистая функция обладает следующими свойствами:
- Зависит только от введенных данных, а не от какого-либо скрытого или внешнего состояния, которое может измениться между вычислениями или вызовами функции.
- Не вызывает изменений вне области видимости, таких как изменение глобальных переменных или параметров, переданных по ссылке.
Но в нашей обычной разработке неизбежны некоторые побочные эффекты, взаимодействие с внешними системами хранения или DOM и т. д., но мы можем сделать их проще в управлении, отделив от основной логики.
Теперь у нас есть небольшое требование: найти запись студента по id и отрендерить ее в браузере (при написании программы подумайте, что она также может быть записана в консоль, базу данных или файл, поэтому подумайте, как сделать ваш код многоразовым) .
// 命令式代码
function showStudent(id) {
// 这里假如是同步查询
var student = db.get(id)
if(student !== null) {
// 读取外部的 elementId
document.querySelector(`${elementId}`).innerHTML = `${student.id},${student.name},${student.lastname}`
} else {
throw new Error('not found')
}
}
showStudent('666')
// 函数式代码
// 通过 find 函数找到学生
var find = curry(function(db, id) {
var obj = db.get(id)
if(obj === null) {
throw new Error('not fount')
}
return obj
})
// 将学生对象 format
var csv = (student) => `${student.id},${student.name},${student.lastname}`
// 在屏幕上显示
var append = curry(function(elementId, info) {
document.querySelector(elementId).innerHTML = info
})
var showStudent = compose(append('#student-info'), csv, find(db))
showStudent('666')
Если вы не понимаете карри, не волнуйтесь, это понятие сложно понять новичкам, и оно играет решающую роль в функциональном программировании.
Вы можете видеть, что функциональный код записывает showStudent как композицию небольших функций, уменьшая длину этих функций. Эта программа не идеальна, но уже может показать множество преимуществ перед императивом.
- гибкий. Есть три многоразовых компонента
- Декларативный стиль, обеспечивающий четкое представление высокоуровневых шагов и повышающий читабельность кода.
- Другой — отделить чистые функции от нечистого поведения.
Мы видим, что вывод чистых функций непротиворечив и предсказуем, и один и тот же ввод будет иметь одно и то же возвращаемое значение, что также называетсяПрозрачность котировок.
Прозрачность котировок
Ссылочная прозрачность — это правильный способ определить чистую функцию. Чистота в этом смысле представляет чистую связь отображения между аргументами функции и возвращаемым значением. Если функция всегда дает один и тот же результат для одних и тех же входных данных, мы говорим, что этоПрозрачность котировок.
Эту концепцию легко понять, достаточно привести два примера.
// 非引用透明
var counter = 0
function increment() {
return ++counter
}
// 引用透明
var increment = (counter) => counter + 1
На самом деле стрелочные функции имеют высокоуровневое название в функциональном программировании, называемое лямбда-выражениями.Такие анонимные функции академически называются лямбда-выражениями, и теперь они поддерживаются в Java.
неизменяемые данные
Неизменяемые данные — это данные, которые нельзя изменить после их создания. Как и во многих других языках, некоторые примитивные типы в JavaScript (String, Number и т. д.) по своей сути являются неизменяемыми, но объекты изменяются везде.
Рассмотрим простой код сортировки массива:
var sortDesc = function(arr) {
return arr.sort(function(a, b) {
return a - b
})
}
var arr = [1, 3, 2]
sortDesc(arr) // [1, 2, 3]
arr // [1, 2, 3]
Этот код, кажется, не проблема, но он вызовет побочные эффекты в процессе сортировки, изменив исходную ссылку, вы можете видеть, что исходная запись становится[1, 2, 3]. Это недостаток языка, и как его преодолеть, будет описано далее.
Суммировать
- Код, использующий чистые функции, никогда не изменяет и не разрушает глобальное состояние, что помогает улучшить тестируемость и ремонтопригодность кода.
- В функциональном программировании используется декларативный стиль, о котором легко рассуждать и который улучшает читаемость кода.
- Функциональное программирование рассматривает функции как строительные блоки, используя первоклассные функции высшего порядка для улучшения модульности кода и возможности его повторного использования.
- Вы можете использовать реактивное программирование для объединения функций, чтобы уменьшить сложность программ, управляемых событиями (это может быть объяснено в отдельной статье позже).
Содержимое взято из «Руководства по функциональному программированию JavaScript».
Добро пожаловать, чтобы обратить внимание на личный публичный аккаунт [Front-end Taoyuan].Частота обновления публичного аккаунта выше, чем у Nuggets.