Воркшоп по функциональному JS
Ничего такого интересного. Если блок кода стрелочной функции можно представить в виде одного выражения, то можно обойтись без фигурных скобок. Если арность функции = 1, то можно обойтись без круглых скобок.
const f = (a) => { return a };
const f = (a) => a;
const f = a => a;
Функцией высшего порядка называют такую, что принимает или возвращает функцию. Все остальные функции первого порядка. Надо заметить, что в js функции являются объектами первого рода, т.е. могут быть присвоены идентификатору.
В примере реализована функция repeat, которая первым параметром принимает функцию, вторым - кол-во вызовов этой функции.
Интересная особенность js в реализации бинарного или
. Почитать лучше в спеке про Binary Logical Operators
Если есть два выражения, которые надо выполнить и они ничего не возвращают, то можно (но не нужно) их выполнить друг за дружкой вот примерно так
f();
repeat();
f() || repeat();
но даже если f()
вернет ч-н не приводимое к true
, то можно еще более заговнить код
f() && false || repeat()
такие дела
Array.prototype.map() создаёт новый массив с результатом вызова указанной функции для каждого элемента массива. В задании хотят каждый элемент в массиве умножить на 2. Легко!
numbers.map(n => n * 2);
Array.prototype.filter() создаёт новый массив со всеми элементами, прошедшими проверку, задаваемую в передаваемой функции. В задании просят массив объектов вот такой структуры {message: String} отфильтровать по длине message меньше 50 символов, затем изменить структуру [{message:String}} -> [String]. Важно, что map может использоваться для изменении структуры данных.
Array.prototype.every() проверяет, удовлетворяют ли все элементы массива условию, заданному в передаваемой функции. Array.prototype.some() проверяет, удовлетворяет ли хоть какой-нибудь элемент массива условию, заданному в передаваемой функции.
В задании передают два списка, вайтлист и список для проверки, и просят проверить вхождение списка в вайтлист. Для этого каждый элемент списка (every) проверяется на вхождение в вайтлист (some). Еще одна важная особенность стрелочных функций - можно опустить круглые скобки для функции одного аргумента!
Array.prototype.reduce() применяет функцию к аккумулятору и каждому значению массива (слева-направо), сводя его к одному значению.
Нужно по входному массиву создать ассоциативный массив, где ключами будут значения входного массива, а значениями - количество повторений.
С reduce вроде все понятно.
Несколько интересных особенностей js в выражении ++acc[c] || 1
.
Во-первых, acc[c]
вернет undefined
если в асс. массиве нет значения для ключа. Без ошибки.
Во-вторых, слабая типизации js вычислит undefined+1
в NaN
ʕ•ᴥ•ʔ
В-третьих, NaN || 42
вычислится в 42, потому что NaN это false, а 42.. это 42 ༼ ͒ ̶ ͒༽
Поведение описано в спецификации в разделе Binary Logical Operators.
JS, я не пойму, ты good, bad or ugly?
Ну и хватит
Рекурсивной называется функция, описанной через себя (рекуррентная запись). типа factorial n = n * factorial n-1
.
У рекурсивной функции должен быть Терминал, т.е. инструкция прекращающая рекурсивный вызов, типа if n === 1 return 1
В задании просят имплементировать reduce, на вход над дадут массив, начальное значение и функцию для вызова в редукторе (правильно написал?). Функция принимает стандартные аргументы: аккумулятор, элемент массива, порядковый номер элемента, массив. Наша реализация должна вернуть значение! Для вычисления мы создадим именованную ф-цию iter от 2 аргументов (индекс и аккумулятор), замкнем на входные параметры и вызвем с начальным значениями.Тело нашего итератора будет содержать Терминал и рекурсивный вызов. В рекурсивном вызове мы инкрементируем индекс и вычисляем новое значение аккумулятора через вызов переданной нам функции. Вот и все.
Function.prototype.call() вызывает функцию с установленными this
и аргументами.
В задании просят проверить, есть ли у объекта свойство quack
.
Object.prototype.hasOwnProperty.call(obj, 'quack')
сделает все что надо.
Фишка в том, что object.hasOwnProperty('quack')
может не сработать по очевидным причинам.
Function.prototype.apply() - вызывает функцию с указанным значением this и аргументами, предоставленными в виде массива. Вызывает добавляем к массиву аргументов еще один в начало, частичное применение фунции нас ждет впереди
Function.prototype.bind() создаёт новую функцию, которая при вызове устанавливает в качестве контекста выполнения this предоставленное значение. В метод также передаётся набор аргументов, которые будут установлены перед переданными в привязанную функцию аргументами при её вызове. Частичное применение функции, клевая штука.
Задание просит сделать map через reduce, давай на вход массив и функцию (и еще thisArg в кач-ве бонуса). В качестве аккумулятора используем массив и добавляем к нему вычисляемые поданной на вход функцией значения. Дело не хитрое. Ну, для иммутбельности еще создаем каждый раз новый массив через arr.concat.
Просят подменить оригинальную функцию шпионской, что в js сделать легко и просто.
Замыкаем объекта result, которому инкрементим свойство count в то время когда сам объект где-то гуляет.
Интересная особенность в отсутвии родного this
и arguments
у стрелочных функций, а чтоб они были приходится использовать инструкцию function