함수형 프로그래밍이란 순수함수(pure function)을 조합하고 공유상태(state state), 변경 가능 데이터(mutable data) 및 부작용(side-effects)을 피하는 기본 원칙에 따라 소프트웨어를 구성하는 프로그래밍 패러다임 이다.
함수형 프로그래밍은 명령적이라기 보단 선언적이다.
명령형 vs 선언형
일반적으로 함수형 프로그래밍에서는 다음 세가지 조건을 만족시켜야 한다.
순수함수란 같은 입력에 대해 항상 같은 출력을 반환하는 함수를 의미한다.
순수함수는 다음과 같은 조건들을 만족해야 한다.
참고 : https://evan-moon.github.io/2020/01/05/what-is-immutable/
고차함수는 다른 함수를 전달인자로 받거나 함수실행의 결과를 반환하는 함수를 의미한다.
일급함수란 함수를 변수로 사용할 수 있는 것을 의미한다.
이를 통해 함수를 파라미터로 사용하거나 리턴 하는데 사용할 수 있다.
const func1 = ((num) => { // 함수를 변수에 저장
return num * 2;
});
console.log(func1(2)); // 4 출력됨
위의 예시와 같이 함수를 변수에 저장할 수 있으며, 변수를 통해 함수를 사용할 수 있다.
const func2 = ((param) => {
return param(3); // 6 출력
});
console.log(func2(func1));
(앞선 예제의 func1이 구현되어 있는 상태)
위의 예시와 같이 함수를 파라미터로 사용할 수 있다.
이 밖에도 함수를 반환하거나 이중 괄호를 사용하는 다양한 방법들이 존재한다.
참고 : https://developer.mozilla.org/ko/docs/Glossary/First-class_Function
자바스크립트에서는 map, filter, reduce 를 사용하여 배열을 좀 더 편리하게 사용할 수 있다.
1. map
map은 배열 각 요소에 대해 주어진 함수를 수행한 결과를 모아 새로운 배열을 반환하는 메서드 이다.
const arr = [1,2,3,4,5];
const arr2 = arr.map((val) => {
return val *= 2;
});
console.log(arr2) // [2,4,6,8,10]
위와 같이 원본 배열에 특정 함수를 적용하여 함수가 적용된 새로운 배열을 생성할 수 있다.
map을 사용할 때 현재요소, 요소의 인덱스, map을 호출한 원본 배열을 파라미터로 넘길 수 있다.
const arr = [1,2,3,4,5];
const arr2 = arr.filter((val) => {
return val >= 3;
});
console.log(arr2); // [3,4,5]
위와 같이 원본 배열에 특정 함수를 적용하여 그 함수를 만족시키는 원소들만을 추출해 낼 수 있다.
const arr = [1,2,3,4,5]
const ret = arr.reduce((acc, cur) => {
console.log(acc, cur);
return acc + cur;
});
console.log(ret);
// 1 2
// 3 3
// 6 4
// 10 5
// 15
위와 같이 reduce는 누적된 값을 저장하는 acc와 현재 요소의 값을 나타내는 cur을 활용하여 함수 실행 결과를 계속하여 누적해 나가며 적용한 후, 마지막 결과를 반환한다.
참고 : https://brunch.co.kr/@swimjiy/15
const arr = [1,2,3,4,5];
let sum = 0;
arr.forEach((val) => {
sum += val;
});
console.log(sum); // 15
위와 같이 배열 내의 모든 요소를 순회하며 그 요소들을 활용할 수 있다.
const arr = [1,2,3,4,5];
const ret = arr.find((val) => {
return val == 3;
});
console.log(ret); // 3
위와 같이 배열 내부를 순회하며 함수의 실행 결과값이 참인 첫번째 원소를 반환해 주는 것을 볼 수 있다.
const arr = [1,3,2,4,5];
const ret = arr.findIndex((val) => {
return val == 3;
});
console.log(ret); // 1
위와 같이 주어진 함수를 만족하는 배열의 원소를 찾아 그 인덱스를 반환해 주는 것을 확인할 수 있다.
참고 : https://freestrokes.tistory.com/115
익명함수란 이름이 없는 함수를 말하며 람다식으로 표현되는 함수 구현을 말한다.
익명함수는 함수의 이름을 사용하지 않고 변수에 함수를 할당하는 것을 의미한다.
변수명을 마치 함수면처럼 사용하여 함수를 호출하거나 변수를 이동시키는 데 사용할 수 있다.
클로저란 함수가 선언될 때 외부의 lexical environment를 참조하게 되는 현상이다.
예시를 통해 보면 좀 더 쉽게 이해가 가능하다.
function outer(){
const val = 10;
return function inner(){
console.log(val * 10);
};
};
const ret = outer();
ret(); // 100
위의 예시를 보면 outer 함수가 inner 함수를 반환하는 형태이다.
ret 변수를 선언하는 과정에서 outer 함수는 종료가 되지만, ret를 실행해 보면 inner 함수 내부의 변수가 아닌 outer 함수의 변수(inner 함수의 외부 변수)를 사용하는 것을 볼 수 있다.
이것이 가능한 이유는 inner 함수가 선언 될 때 주변의 lexical environment와 번들로 묶였기 때문이다.
따라서 inner 만을 시행할 때 같이 묶인 주변 환경을 사용할 수 있는 것이다.
클로저를 사용하여 전역변수의 사용을 줄일 수 있고, 비슷한 형태의 코드를 재사용 할 수 있다는 장점이 있다.