functionality - garevna/js-course GitHub Wiki
🎓 Чистая функция - это функция, которая:
- при одних и тех же значениях аргументов возвращает один и тот же результат ( предсказуемое поведение )
- не влияет на внешнее окружение, т.е. не изменяет значения внешних переменных ( не создает "побочных эффектов" )
- не зависит от состояния окружения, потому что не использует внешние переменные в своих вычислениях
🎓 Ссылочная прозрачность ( referential transparency ) - это возможность заменить вызов функции с заданным набором аргументов результатом ее вызова
let func = ( x, y, z ) => x + y - zВызов функции func ( 3, 4, 2 ) всегда возвращает 5,
поэтому можно заменить func ( 3, 4, 2 ) значением 5
А вот такая функция не будет обладать свойством referential transparency,
поскольку результат ее работы будет случайным числом:
let func = ( x, y, z ) => x + y - z * Math.random()В следующем примере функция counter также не будет ссылочно-прозрачной, поскольку каждый вызов этой функции будет возвращать новый результат:
let makeCounter = () => {
let counter = 0
return () => counter++
}
let counter = makeCounter ()🎓 Иммутабельность ( immutability ) - это устойчивость к изменениям
Иммутабельные данные - это данные, которые не меняются с течением времени
В следующем примере переменные number и sum трижды меняют свое значение в процессе выполнения цикла:
let numbers = [ 10, 5, 7 ]
let sum = 0
for ( let number of array ) {
sum += number
}А если использовать функцию summation:
let summation = array => {
let index = 0, sum = 0
return ( function recurse () {
sum += array [ index++ ]
return index < array.length ? recurse () : sum
})()
} то после вызова
let numbers = [ 10, 5, 7 ]
let sum = 0
summation( numbers ) // 22массив numbers и переменная sum не изменятся, т.е. функция summation не производит внешних эффектов
🎓 Функция высшего порядка — это функция, принимающая в качестве аргументов другие функции или возвращающая другую функцию в качестве результата
Поскольку функции в JS являются объектами, действовать с ними можно абсолютно так же, как с любым объектом:
- собирать в структуры ( массивы, объекты )
- передавать в качестве аргумента
- возвращать в качестве результата ( что, собственно, и делает конструктор
Function)
Одним словом, все, что мы можем делать с объектами, можно делать с функциями, поскольку функции - это всего лишь объекты класса Function
function frog () {
console.log ( "frog" )
}
function elefant () {
console.log ( "elefant" )
}
function animal ( func ) {
func ()
}В этом примере функция animal получает в качестве аргумента ссылку на функцию, которую и вызывает
Мы можем передавать функции animal различные функции
Вызовем функцию animal:
animal ( frog )
animal ( elefant )и в консоли мы увидим:
frog
elefantОднако если аргумент функции animal окажется не функцией, то при попытке его вызова ( с круглыми скобками ) будет сгенерировано исключение ( TypeError )
Во избежание этого немного изменим код функции animal, добавив проверку типа аргумента:
function animal ( func ) {
typeof func === 'function' ? func () : null
}Создадим элемент div и добавим его в document.body
Установим свойство id этого элемента равным "sample"
Изменим код функций frog() и elefant():
function frog () {
return "frog"
}
function elefant () {
return "elefant"
}Теперь объявим функцию newFunc(), которая будет создавать новый элемент p, вставлять его в контейнер с идентификатором elemId и устанавливать его содержимое ( innerHTML ) с помощью функции, переданной аргументом:
function newFunc ( func, elemId ) {
var elem = document.getElementById ( elemId )
if ( !elem || !elem.nodeType || elem.nodeType !== 1 ) return
function makeElem () {
var x = document.createElement ( "p" )
elem.appendChild ( x )
x.innerHTML = func ()
console.log ( x )
}
if ( typeof func === 'function' )
makeElem ( func, elem )
}Вызовем функцию newFunc, передав ей функцию frog в качестве первого аргумента, а вторым аргументом передадим ей id созданного нами элемента ( "sample" ):
newFunc ( frog, "sample" )В результате на странице появится новый элемент с текстом, который возвращает функция frog()
Теперь вызовем функцию newFunc(), передав ей функцию elefant():
newFunc ( elefant, "sample" )В результате на странице появится новый элемент с текстом, который возвращает функция elefant()
Теперь объявим функцию createFunction(), которая будет возвращать функцию:
function createFunction ( param ) {
return function () {
console.log ( 'function ', param )
}
}и создадим с ее помощью две новые функции: firstFunc() и secondFunc():
var firstFunc = createFunction ( "First" )
var secondFunc = createFunction ( "Second" )Вызовем каждую из этих функций:
firstFunc ()
secondFunc ()В консоли мы увидим:
function First
function Second