미래 지향적인 웹 앱 구축: The Codest의 전문가 팀이 제공하는 인사이트
The Codest가 최첨단 기술로 확장 가능한 대화형 웹 애플리케이션을 제작하고 모든 플랫폼에서 원활한 사용자 경험을 제공하는 데 탁월한 성능을 발휘하는 방법을 알아보세요. Adobe의 전문성이 어떻게 디지털 혁신과 비즈니스를 촉진하는지 알아보세요...
이번 글은 JavaScript의 함수형 프로그래밍의 힘을 다룬 시리즈 글의 두 번째 파트입니다. 이 글을 확인하여 결합기에 대한 지식을 넓혀보세요.
결합자는 함수, 변수 또는 다른 결합자를 결합할 수 있는 상위 수준의 함수입니다. 일반적으로 자체 변수나 비즈니스 로직에 대한 선언은 포함하지 않습니다. 함수 프로그램에서 컨트롤을 플러시하는 유일한 함수입니다.
이 글에서는 그 중 몇 가지를 다루려고 합니다:
결합기는 아무것도 반환하지 않는 함수에 매우 유용합니다. 매개변수가 전달되는 함수를 취한 다음 반환합니다.
선언
const tap = (fn) => (value) => {
fn(value);
반환 값;
};
필수 예제
const [items, setItems] = useState(() => [])
axios
.get('http://localhost')
.then({ data } => {
setItems(data)
console.log(data)
onLoadData(data)
}).then(...) // 정의되지 않은 반환 - 프라미스의 데이터가 수정되었습니다.
선언적 예제
const [items, setItems] = useState(() => [])
axios
.get('http://localhost')
.then(({ 데이터 }) => 데이터)
.then(tap(setItems)) // (data) => { setItems(data); return data }
.then(tap(console.log)) // 하나의 그때 = 하나의 함수 = 하나의 책임
.then(tap(onLoadData))
.then(...) // 여전히 원본 데이터에 액세스 가능
// 열기/닫기 원칙을 쉽게 유지
함수의 인수를 분할하여 순차적으로 호출할 수 있도록 합니다.
선언
const curry = (fn) => {
const curry = (...args) => {
if (fn.length !== args.length){
return curried.bind(null, ...args)
}
return fn(...args);
};
return curried
};
예
const curry = (fn) => {
const curry = (...args) => {
if (fn.length !== args.length){
return curried.bind(null, ...args)
}
return fn(...args);
};
return curried
};
const sum = (a, b, c) => a + b + c
const currySum = curry(sum)
/*
가능한 호출
currySum(a)(b)(c),
currySum(a)(b,c),
currySum(a,b)(c),
currySum(a,b,c)
*/
currySum(1) // (b, c) => 1 + a + b 또는 (b) => (c) => 1 + a + b
currySum(5)(10) // (c) => 5 + 10 + b
currySum(5, 10) // (c) => 5 + 10 + b
currySum(5)(10)(20) // 35
currySum(5, 10)(20) // 35
currySum(5)(10, 20) // 35
const divideBy = curry((a, b) => b / a)
const multiplyBy = curry((a, b) => a * b)
const divideByTwo = divideBy(2)
divideByTwo(10) // 5를 반환합니다.
const multiplyByFive = multiplyBy(5)
multiplyByFive(10) // 50을 반환합니다.
구성을 통해 한 함수에서 다른 함수로 데이터를 전달할 수 있습니다. 함수에 동일한 수의 인수를 사용하는 것이 중요합니다. 파이프와 컴포지션의 차이점은 파이프는 함수를 처음부터 마지막까지 실행하고 컴포지션은 마지막부터 호출한다는 점입니다.
선언
const pipe = (...fns) => (value, ...args) =>.
fns.reduce((v, f, i) => =>
i === 0
? f(v, ...args)
: f(v),
value);
const compose = (...fns) => (value, ...args) =>.
fns.reduceRight((v, f, i) => =>
i === (fns.length - 1)
? f(v, ...args)
: f(v),
value);
const pipe = (...fns) => (value, ...args) =>.
fns.reduce((v, f, i) => =>
i === 0
? f(v, ...args)
: f(v),
value);
const compose = (...fns) => (value, ...args) =>.
fns.reduceRight((v, f, i) => =>
i === (fns.length - 1)
? f(v, ...args)
: f(v),
value);
필수 예제
const sine = (val) => Math.sin(val * Math.PI / 180) // 읽을 수 없음
sine(90) // 1 반환
선언적 예제
const 사인 = 파이프(
multiplyBy(Math.PI) // ↓ val * Math.PI
divideBy(180), // ↓ val * Math.PI / 180
Math.sin, // ↓ Math.sin(val * Math.PI / 180)
)
const sine = compose(
Math.sin, // ↑ Math.sin(val * Math.PI / 180)
divideBy(180), // ↑ val * Math.PI / 180
multiplyBy(Math.PI) // ↑ val * Math.PI
)
sine(90) // 반환값 1
포크 결합기는 값을 두 가지 방식으로 처리하고 그 결과를 결합하려는 경우에 유용합니다.
선언
const fork = (join, fn1, fn2) => (value) => join(fn1(value), fn2(value));
예
const length = (array) => array.length
const sum = (array) => array.reduce((a, b) => a + b, 0)
const divide = (a, b) => a / b
const arithmeticAverage = 포크(divide, sum, length)
arithmeticAverage([5, 3, 2, 8, 4, 2]) // 4를 반환합니다.
이 결합기는 두 개의 함수를 취하고 참이면 첫 번째 함수의 결과를 반환합니다. 그렇지 않으면 두 번째 함수의 결과를 반환합니다.
선언
const alt = (fn, orFn) => (값) => fn(값) || orFn(값)
예
const users = [{
uuid: '123e4567-e89b-12d3-a456-426655440000',
name: 'William'
}]
const findUser = ({ uuid: searchesUuid }) =>.
users.find(({ uuid }) => uuid === searchesUuid)
const newUser = data => ({ ...data, uuid: uuid() // 새 uuid 생성 })
const findOrCreate = alt(findUser, newUser)
findOrCreate({ uuid: '123e4567-e89b-12d3-a456-426655440000' }) // 윌리엄 객체를 반환합니다.
findOrCreate({ name: 'John' }) // 새 uuid를 가진 John 객체를 반환합니다.
이 함수는 많은 독립 함수를 허용하고 각 함수에 동일한 매개변수를 전달합니다. 일반적으로 이러한 함수는 값을 반환하지 않습니다.
선언
const seq = (...fns) => (val) => fns.forEach(fn => fn(val))
예
const appendUser = (id) => ({ name }) => {
document.getElementById(id).innerHTML = name
}
const printUserContact = pipe(
findOrCreate, // 사용자 반환
seq(
appendUser('#contact'), // user => void
console.log, // user => void
onContactUpdate // 사용자 => void
)
)
printUserContact(userData)