Today I Learned
일급 객체 (First Class Object)
- 자바스크립트에서 함수는 객체로 취급되기 때문에 다음과 같은 특성을 지닌다.
- 리터럴로 생성 가능
- 변수에 할당 가능
- 함수의 인자로 전달 가능
- 함수의 리턴값으로 리턴 가능
- 동적으로 프로퍼티를 생성/할당 가능
- 일급 객체로서의 함수란?
- 함수의 인자로 전달, 변수에 대입 등이 가능한 객체
선언형 프로그래밍 (Declarative Programming) vs. 명령형 프로그래밍 (Imperative Programming)
- 선언형 프로그래밍은 무엇(What)을 할 것인가에, 명령형 프로그래밍은 무엇을 어떻게(How)할 것인지에 초점을 둔 프로그래밍 패러다임이다.
- 명령형 프로그래밍 : 알고리즘 O, 목표 X
- 선언형 프로그래밍 : 알고리즘 X, 목표 O
- 명령형은 특정 문제 하나를 해결하는 것에 초점을 두고 있어서 재사용성이 낮다.
- 선언형은 추상화된 코드를 사용하여 재사용성을 높인다. 선언형 프로그래밍은 명령형 프로그래밍 방식보다 높은 수준의 추상화를 가능하게 한다.
- 명령형 프로그래밍에는 절차적 프로그래밍, 객체지향 프로그래밍이 있다.
- 선언형 프로그래밍에는 함수형 프로그래밍이 있다.
- 자바스크립트에서는 절차적/객체지향/함수형 프로그래밍 모두 가능하다.
const nums = [3, 5, 8, 1, 12, 7, 4, 9];
const numsBiggerThan5 = (arr) => {
const result = [];
for (let el of arr) {
if (el > 5) {
result.push(el);
}
}
return result;
}
const numsBiggerThan5 = (arr) => {
return arr.filter(el => el > 5);
}
추상화
- 복잡한 자료, 모듈, 시스템 등으로부터 핵심적인 개념 또는 기능을 간추려 내는 것
- 어떤 함수를 사용할 때 그 함수 내부의 로직을 몰라도 사용할 수 있다. 예를 들 어 자바스크립트 내장 메서드인
filter()
를 사용할 때 이 메서드의 로직은 모르지만 인자만 정확하게 전달하면 원하는 값을 얻을 수 있다. 이것이 추상화의 예로 로직(알고리즘)을 몰라도 무엇을 하고자 하는지(목표)만 명확하면 문제를 해결할 수 있다.
- 추상화는 이면의 복잡한 로직을 고민하지 않게 하여 생산성을 향상시킨다.
- 고차함수는 추상화의 수준을 사고(함수) 수준으로 끌어올린다.
고차함수/고계함수 (Higher Order Function)
- 다른 함수를 인자로 전달 받거나 함수를 리턴하는 함수
- 자바스크립트의 내장함수들 중에서 함수를 인자로 받는
filter()
, map()
, reduce()
같은 함수들이 고차함수의 예다.
function isEven(num) {
return num % 2 === 0;
}
function getEvenNums(arr) {
return arr.filter(isEven);
}
콜백함수
- 고차함수의 인자로 넘겨져 호출되는 함수
- 명시적으로 호출되지 않고 등록만 되어 있다가 이벤트 발생 등 특정 시점에서 호출된다. (대표적으로 이벤트 핸들러 처리 함수)
const scrollTopBtn = document.querySelector('#scroll-top-btn');
function scrollTop() {
window.scrollTo({ top: 0, behavior: 'smooth' });
}
scrollTopBtn.addEventListener('click', scrollTop);
커링함수 (Currying Function)
- 함수형 프로그래밍을 활용한 함수로, n개의 인자를 받는 함수를 하나의 인자를 받는 n개의 함수 변환한 것을 말한다.
func(a, b, c)
-> func(a)(b)(c)
- 변하는 부분과 변하지 않는 부분을 나눠 변하지 않는 부분을 고정하고 변하는 부분을 열어두는 함수 추상화 기법이다.
- 모든 인자를 받을 때까지 계속해서 함수를 생성한다.
- 함수 인자수를 한 개로 줄여 재활용성을 높였다.
- 함수 실행을 원하는 시점까지 미룰 수 있어서 비동기 관리에 용이하다.
const curry = (func) => {
return function curriedFunc(...args) {
if (args.length >= func.length) {
return func(...args);
} else {
return (...args2) => curriedFunc(...args, ...args2);
}
};
};
함수 조합 (Function Composition)
- 함수 조합은 둘 이상의 함수를 묶어 하나로 만드는 것
- 커링과 함수 조합은 서로 관계되어 있으며 함께 쓰였을 때 시너지를 발생시킨다.
const compose = (...funcs) => (initialValue) => funcs.reduceRight((value, func) => func(value), initialValue);