функция
обязательно нужно вернуть результат через
chain из lodash
позволяет применить много функций сразу для одного значения. каждой следующей функции передаёт результат предыдущейобязательно нужно вернуть результат через
.value()
пример:_.chain('mememe')
.capitalize()
.value();
//Mememe
пример посложнее:_.chain([36, 40, 1, 3, 1, 1, 1, 1])тут важно заметить, что uniq это тоже лоудашевская функция, доступная внутри
.sort((a, b) => a - b)
.uniq()
.value();
// [1, 3, 36, 40]
chain без _функция высшего порядка это функция, которая в качестве аргументов принимает другие функции или возвращает функцию в качестве результата
например
например
onEventListenerbutton.addEventListener("click", function() {
//do stuff
})декоратор это функция, которая расширяет функционал переданной ей функции
пример:
пример:
hoc — функция, которая принимает компонент и возвращает новый компонент с расширенным функционалом
то есть hoc это частный случай декоратора
https://reactjs.org/docs/higher-order-components.html
то есть hoc это частный случай декоратора
https://reactjs.org/docs/higher-order-components.html
legacy.reactjs.org
Higher-Order Components – React
A JavaScript library for building user interfaces
вернёмся к фп
преимущество такой колбасы в том, что мы избегаем циклов и создания переменных — повышаем читаемость и сокращаем количество мест в которых можем ошибиться
_.chain(persons)
.filter(isValid)
.map(_.property('address.country'))
.reduce(gatherStats, {})
.values()
.sortBy('count')
.reverse()
.first()
.value()
.name; //-> 'US'
преимущество такой колбасы в том, что мы избегаем циклов и создания переменных — повышаем читаемость и сокращаем количество мест в которых можем ошибиться
в
_.chain ничего не выполняется, пока не будет вызвана функция value() — где-то здесь и начинаются отложенные вычисления_.mixin позволяет добавлять в лоудашевский (не только) объект свои методыпример
_.mixin({
test: () => 'hello world',
});
const res = _.test();
console.log(res);
// hello worldобратим внимание на вот такой объект примеси:
_.mixin({
select: _.map,
from: _.chain,
where: _.filter,
sortBy: _.sortByOrder,
});
он делает js-код похожим на sql-запрос_.from(persons)sql супир
.where(p => p.birthYear > 1903 && p.address.country !== 'US')
.sortBy(['firstname'])
.select(p => p.firstname)
.value();
Рекурсия
Понять рекурсию несложно, нужно научиться мыслить рекурсивно
вот простая рекурсивная функция:
в нашем случае вот оно:
но есть способы это оптимизировать, ето я узнаю только в седьмой главе (сейчас я на третьей)
Понять рекурсию несложно, нужно научиться мыслить рекурсивно
вот простая рекурсивная функция:
function sum(arr) {
if(_.isEmpty(arr)) {
return 0;
}
return _.first(arr) + sum(_.rest(arr));
}
sum([]); //-> 0
sum([1,2,3,4]);
у неё есть базовая ветвь или условие возвратав нашем случае вот оно:
if(_.isEmpty(arr)) {
return 0;
}
рекурсивная функция вызывает сама себя, и сохраняет все эти вызовы во внутреннем стеке контекстов выполнения. И только когда алгоритм достигнет условия возврата, выполнятся вложенные вызовы1 + sum[2,3,4]из-за множества вложенных контекстов, с производительностью у рекурсии не очень
1 + 2 + sum[3,4]
1 + 2 + 3 + sum[4]
1 + 2 + 3 + 4 + sum[]
1 + 2 + 3 + 4 -> halts, stack unwinds
1 + 2 + 7
1 + 9
10
но есть способы это оптимизировать, ето я узнаю только в седьмой главе (сейчас я на третьей)
ирл рекурсия чаще всего используется чтобы выпендриться на собеседовании или обойти древовидную структуру данных (дом-дерево например)
дальше в книжке идёт несколько длинных примеров кода создания древовидной структуры и методов её обхода
главное что стоит запомнить:
- в родительском узле есть дети, а у детей есть ссылки на родителей
- в этом случае мы обходим дерево в ширину (а можно ещё и в глубину или рандомно или еще как-то)
дальше в книжке идёт несколько длинных примеров кода создания древовидной структуры и методов её обхода
главное что стоит запомнить:
- в родительском узле есть дети, а у детей есть ссылки на родителей
- в этом случае мы обходим дерево в ширину (а можно ещё и в глубину или рандомно или еще как-то)
условие возврата тут находится в строке 17 —
изначально дерево ето
строку 8 можно пропустить
дальше в строке 12 мы смотрим, есть ли у ноды дети и если есть то мы рекурсивно вызываем эту же функцию на детях и детях детей.
и после детей второго уровня возвращаемся к детям первого уровня и проверяем их
и когда все дети проверены и у текущей ноды нет детей мы возвращаем дерево
return treeизначально дерево ето
null так что мы его создаём с переданной снаружи нодойстроку 8 можно пропустить
дальше в строке 12 мы смотрим, есть ли у ноды дети и если есть то мы рекурсивно вызываем эту же функцию на детях и детях детей.
и после детей второго уровня возвращаемся к детям первого уровня и проверяем их
и когда все дети проверены и у текущей ноды нет детей мы возвращаем дерево
это всё довольно запутано, но доступно для понимания при троганьи руками и консоль.логами
при желании трогать можно здесь:
https://livebook.manning.com/book/functional-programming-in-javascript/chapter-3/193
при желании трогать можно здесь:
https://livebook.manning.com/book/functional-programming-in-javascript/chapter-3/193
Композиция функций
Это процесс группирования сложного поведения, разделенного на простые задачи
Главное преимущество — отделение описания функции от её вычисления
например
Данная программа начнет вычисляться только когда произойдет вызов функции
Это процесс группирования сложного поведения, разделенного на простые задачи
Главное преимущество — отделение описания функции от её вычисления
например
const str = `We can only see a short distance ahead but we can see plenty there that needs to be done`;
const explode = (str) => str.split(/\s+/);
const count = (arr) => arr.length;
const countWords = R.compose(count, explode);
Данная программа начнет вычисляться только когда произойдет вызов функции
countWordsсамое сложное тут — функции выполняются снизу вверх
напротив каждой я написала результат выполнения, так что в целом всё понятно
напротив каждой я написала результат выполнения, так что в целом всё понятно