1급 함수란 자바스크립트에서 함수가 다음 조건을 충족하는 것을 의미한다.
이러한 개념을 활용하여 함수형 프로그래밍을 구현할 수 있다.
// 함수를 변수에 할당
const add = function(a, b) {
return a + b;
};
// 함수를 다른 함수의 매개변수로 전달
function operate(func, x, y) {
return func(x, y);
}
// 함수를 다른 함수에서 반환
function makeAdder(x) {
return function(y) {
return x + y;
};
}
console.log(operate(add, 3, 4)); // 출력: 7
const addFive = makeAdder(5);
console.log(addFive(3)); // 출력: 8
고차함수란 다른 함수를 인자로 받거나, 함수를 반환하거나, 둘 다 할 수 있는 함수를 의미한다.
이를 구현하기 위해서는 위에서 언급한 1급 함수의 세 가지 특성을 활용한다.
// 고차 함수 구현 예제
// 다른 함수를 인자로 받는 고차 함수
function higherOrderFunction(func, x, y) {
return func(x, y);
}
// 함수를 반환하는 고차 함수
function createMultiplier(multiplier) {
return function(x) {
return x * multiplier;
};
}
const double = createMultiplier(2);
const triple = createMultiplier(3);
console.log(higherOrderFunction(add, 3, 4)); // 출력: 7
console.log(double(5)); // 출력: 10
console.log(triple(5)); // 출력: 15
일급함수를 활용한 함수형 프로그래밍에서는 부수 효과를 최소화하는 하는 것이 중요하다.
다음과 항목들을 함수형 프로그래밍에 적용하면 부수 효과를 최소화할 수 있다.
함수를 안전하게 합성하기 위한 value를 가지고 있는 객체
):예측 가능성 (순수 함수는 동일한 입력에 대해 항상 동일한 출력을 반환하기 때문에 프로그램의 동작을 예측하기 쉽게 한다.
)
테스트 용이성(부수 효과가 없는 순수 함수는 테스트하기가 매우 쉽다. 함수를 테스트할 때 외부 상태나 환경을 신경 쓸 필요가 없기 때문이다.
)
디버깅 용이성(순수 함수는 외부 상태에 의존하지 않으므로 디버깅이 용이하다. 함수의 동작을 이해하기 위해 함수 자체만을 고려하면 되기 때문이다.
)
병렬 처리와 안전성(순수 함수는 외부 상태에 의존하지 않으므로 여러 스레드에서 안전하게 병렬 처리될 수 있다. 부수 효과가 없기 때문에 동시에 여러 스레드에서 함수를 호출해도 안전하게 동작한다.
)
이러한 이점들은 순수 함수가 함수형 프로그래밍에서 매우 중요한 개념으로 간주되는 이유 중 하나이며, 순수 함수를 사용하면 프로그램의 안정성과 확장성을 높일 수 있다.
클로저란 다음과 같은 특징을 가지고 있는 함수를 의미한다.
function outerFunction() {
let outerVariable = '외부 변수';
// 내부 함수 (클로저)
function innerFunction() {
console.log(outerVariable); // 외부 변수에 접근
}
// 내부 함수 반환
return innerFunction;
}
// outerFunction을 호출하여 innerFunction을 반환받음
const closureExample = outerFunction();
// closureExample을 호출하여 내부 함수 실행
closureExample(); // 출력: "외부 변수"
이 예제에서는 outerFunction
내부에 선언된 innerFunction
이 클로저이다.
outerFunction
이 실행되고 그 결과로 innerFunction
함수가 반환된다.
반환된 내부 함수인 closureExample
을 호출할 때, 이 함수는 외부 스코프에 있는 outerVariable
변수에 접근할 수 있다.
클로저는 주로 함수 내에서 외부 변수를 기억하고 유지해야 할 때 사용된다.
이를 통해 정보 은닉, 비동기 작업 관리, private 멤버 구현 등 다양한 기능을 구현할 수 있다.
// 커링되지 않은 함수
function add(a, b, c) {
return a + b + c;
}
// 커링 함수
function curriedAdd(a) {
return function(b) {
return function(c) {
return a + b + c;
};
};
}
// 커링된 함수를 사용하여 부분적으로 적용된 함수 생성
const add5 = curriedAdd(5);
const add5And6 = add5(6);
console.log(add5And6(7)); // 출력: 18
// 부분 적용 함수
function partial(func, ...args) {
return function(...rest) {
return func.apply(this, args.concat(rest));
};
}
// 원래 함수
function multiply(a, b, c) {
return a * b * c;
}
// 부분 적용된 함수 생성
const partialMultiply = partial(multiply, 2);
console.log(partialMultiply(3, 4)); // 출력: 24
따라서, 커링은 다중 인자 함수를 단일 인자 함수들로 변환하는 기법이며, 부분 적용은 함수의 일부 인자를 미리 입력하여 새로운 함수를 생성하는 기법이다.
커링은 주로 인자를 고정하여 함수를 재사용하는 데 사용되고, 부분 적용은 함수의 유연성을 유지하면서 일부 인자를 미리 결정할 때 사용한다.