Mateusz Pokora
Software engineer od 6 lat.
Aktualnie pracuje w firmie HTDevelopers.
Javascript jest językiem wielodogmatowym, możemy programować w nim zarówno funkcyjnie jak i obiektowo.
// Statement
if (/* warunek */) {
return getUser();
} else {
return null;
}
// Expression
const user = getUser()
Opisywanie rzeczy w sposób "czym są" - funkcje matematyczne
W przeciwieństwie do programowania imperatywnego - wypisywanie instrukcji krok po kroku.
class Car {
constructor(params) {
this.speed = params.speed;
this.name = params.name;
this.color = params.color;
}
accelerate = () => {
this.speed = this.speed + 10;
}
break = () => {
this.speed = 0;
}
}
1 const myCar = new Car({ name: "Toyota", color: "black", speed: 50})
...
50 myCar.accelerate() // what's the current speed??
Aby znać wartość "speed" w 50 linijce musimy prześledzić poprzednie 49
// Data container class
class Car {
constructor(params) {
this.speed = params.speed;
this.name = params.name;
this.color = params.color;
}
}
// Operations on data
class CarActions {
accelerate = (car) => {
return new Car({..., speed: car.speed + 10})
}
}
1 const myCar = new Car({ name: "Toyota", color: "black", speed: 50})
...
50 CarActions.accelerate(myCar) // new instance of object with updated fields
// Mutation
const toyota = { ... , name: 'Toyota' };
toyota.name = "Maserati"
// No mutation
const myCar = { ... , name: 'Toyota' };
const maserati = {...toyota, name: "Maserati" };
// Mutation
const carList = [{ ... , name: 'Toyota' }, { ... , name: 'Opel' }];
carList.push({... , name: 'Maserati' });
// No mutation
const carList = [{ ... , name: 'Toyota' }, { ... , name: 'Opel' }];
const updatedList = [...carList, {... , name: 'Maserati' }]
const arr1 = [{a: 10, b: 5}];
console.log(arr1) => [{a: 10, b: 5}]
const arr2 = arr1.slice();
console.log(arr2) => [{a: 10, b: 5}]
arr2[0].b = 15;
console.log(arr2) => [{a: 10, b: 15}]
console.log(arr1) => [{a: 10, b: 15}]
JS arrays and object are shallow copied by default!!!!!
# pure
const add = (a, b) => (a + b)
# not pure
const fetchCar(carId) => axios.get(...)
const Button = ({label, onClick}) => (
<button onClick={onClick}>{label}</button>
)
Brak side effectów:
http://github.com/pokorson/nodeschool-fp-js
Array.map
Array.filter
Array.reduce
Array.flatMap
https://www.tibco.com/blog/wp-content/uploads/2015/05/lego.jpg
add = (x, y) => ( x + y )
add(5, 10) => 15
-------------------------
# Currying
add = (x, y) => ( x + y )
createrAdder = curry(add)
add5 = createAdder(5)
add5(10) => 15
const add5 = (x) => ( x + 5 )
const multiplyBy10 = (x) => ( x * 10 )
multiplyBy10( add5(3) ) === compose(multiplyBy10, add5)(3)
multiplyBy10(
add5(
subtract2(
divideBy5(20)
)
)
)
vs
compose(
multiplyBy10,
add5,
subtract2,
divideBy5
)(3)
const compose = (...fns) => {
return (args) => fns.reduceRight((result, currentFn) => currentFn(result), args)
}
const getLastPremiumUserName = compose(
prop('fullName'),
map(user => {...user, fullName: `${user.firstName} ${user.lastName}` }),
last,
sortByRegistrationDate,
filter(user => user.isPremium)
)
Zbiory funkcji pozwalające na większą kompozycje logiki (ifElse, bezpieczne odczytywanie atrybutów w obiektach, map na tablicach i obiektach)
const R = require('ramda')
const getLastPremiumUserName = R.compose(
R.prop('fullName'),
R.map(user => {...user, fullName: `${user.firstName} ${user.lastName}` }),
R.last,
R.sortByRegistrationDate,
R.filter(R.prop('isPremium'))
)
npm install --save ramda
https://ramdajs.com/