함수형 프로그래밍은 함수를 다른 함수의 파라미터로 넘길 수도 있고, 반환(return) 값으로 함수를 받을 수 있는 프로그래밍 형태를 말한다.
자바스크립트를 학습하다보면, 자바스크립트가 함수를 일급 시민(fist-clss citizen)으로 취급한다는 것을 들어봤을 것이다. 왜냐하면 자바스크립트 또는 함수형 프로그래밍 언어 함수들은 전부 객체(Object)이기 때문이다.
자바스크립트에서는 위에서 언급했듯이 1급 객체로 취급한다.
그렇기 때문에, 자바스크립트에서 object, string, number와 같은 타입으로 할 수 있는 것은, 함수로도 할 수 있다. 파라미터로 다른 함수에 넘길 수도 있고(콜백), 함수를 다른 변수에 할당하거나, 다른 곳으로 넘길 수도 있다. 이러한 특성때문에 1급 객체 - 퍼스트 클래스 함수라 불리는 것이다.
const square = function(x) {
return x * x;
}
// print 25
squares(5);
// 함수를 여러곳에 넘길 수도 있다.
const foo = squares;
foo(6) // print 36
function formalGreeting() {
console.log('How are you?');
}
function casualGreeting() {
console.log('what's up?');
}
function greet(type, greetFormal, greetCasual) {
if(type === 'formal') {
greetFormal();
} else if(type === 'casual') {
greetCasual();
}
}
// prints "What's up?"
greet('casual', formalGreeting, casualGreeting);
고차 함수는 함수를 인자로 전달받거나, 함수를 결과로 반환하는 함수를 말한다.
자바스크립트의 함수는 일급 객체이므로 값처럼 인자로 전달할 수 있으며 반환할 수 있다.
Array.prototype.map, Array.prototype.filter, Array.prototype.reduce 등 해당 배열 메소드들이 언어 내부에 포함된 (built-in) 고차함수입니다.
// 함수를 인자로 전달받고 함수를 반환하는 고차 함수
function makeCounter(func) {
// 자유 변수, count의 상태는 유지되어야 한다.
let num = 0;
// 클로저. count의 상태를 유지한다.
return function() {
// predicate는 자유 변수 num의 상태를 변화시킨다.
num = predicate(count);
return num;
};
}
// 보조 함수
function increase(n) {
return ++n;
}
// 보조 함수
function decrease(n) {
return --n;
}
// makeCounter는 함수를 인수로 전달받는다. 그리고 클로저를 반환한다.
const increaser = makeCounter(increase);
console.log(increaser()); // 1
console.log(increaser()); // 2
//makeCounter는 함수를 인수로 전달받는다. 그리고 클로저를 반환한다.
const decreaser = makeCounter(decrease);
console.log(decreaser()); // -1
console.log(decreaser()); // -2
함수형 프로그래밍은 순수 함수(Pure Function)와 보조 함수의 조합을 로직 내에 존재하는 조건문과 반본문을 제거해 복잡성을 해결하고 변수의 사용을 억제해 상태 변경을 피하려는 프로그래밍 패러다임이다.
조건문이나 반복문은 로직의 흐름을 이해하기 어렵게 해 가독성을 해치고, 변수의 값은 누군가에 의해 언제든지 변경될 수 있어 오류 발생의 근본적인 원인이 될 수 있다.
함수형 프로그래밍은 결국 순수 함수를 통해 부수효과(side Effect)를 최대한 억제해 오류를 피하고 프로그램의 안정성을 높이려는 노력의 한 방법이라고 할 수 있다.
const strArray = ['javaScript', 'Python', 'PHP', 'Java', 'C'];
function mapForEach(arr, fn) {
const newArray = [];
for (let i = 0; i < arr.length; i++) {
newArray.push(fn(arr[i]));
}
return newArray;
}
const lenArray = mapForEach(strArray, function(item) {
return item.length;
});
console.loig(lenArray); // print [10, 6, 3, 4, 1]
위 예제에서, 배열과 콜백함수 fn
을 받는 고차 함수 mapForEach
를 만들었다.
이 함수는 제공받은 배열을 반복하고, newArray,push
함수 내부에서 각각의 반복마다 콜백 함수 fn
을 호출한다.
콜백함수 fn
은 배열의 현재 요소를 받고, newArray
의 내부에 저장된 요소의 길이를 반환한다. 반복문이 종료된 이후, newArray
가 반환되고, lenArray
에 할당된다.