💬 들어가기 앞서
유인동 님의 함수형 자바스크립트 강의를 기반으로 학습한 내용을 정리합니다. 관련해 더 탐구한 내용이나, 지엽적인 부분은 모던 자바스크립트 딥다이브와 You Don't Know JS Yet 서적을 참고하여 정리하고 있습니다. 본문 내 잘못된 부분이나 궁금하신 부분은 언제든 코멘트 남겨주세요. 감사합니다.
📚 일급함수와 고차함수
평가
- 코드가 계산되어 값을 만드는 것
- 연산자 우선순위에 의해 순서를 갖고 평가가 이루어진다.
- 사칙연산 뿐만 아니라 배열, 객체 등 다양한 형태와 복합적으로 평가될 수도 있다.
일급
- 값으로 다룰 수 있다.
- 변수에 할당할 수 있다.
- 함수의 인자 혹은 결과 (Return 값)으로 사용될 수 있다.
const a = 10;
const add10 = a => a + 10;
const r = add10(a)
자바스크립트에서 객체 타입의 값인 함수는 일급이다. 따라서, 함수를 값으로 다룰 수 있다는 뜻이다. 함수 내부에 인자를 집어넣어 한 번 더 평가된 결과 또한 값으로 다룰 수 있다.
💬 함수 리터럴로 생성한 함수 객체를 변수에 할당한 함수 정의 방식을 함수 표현식이라고 한다.
💬 반대로 함수를 변수에 할당하지 않고 function문 등을 통해 함수를 정의한 방식을 함수 선언문이라고 한다. 함수 정의 방식에 대해서는 해당 아티클 후반부에서 더 자세히 다룰 예정이다.
함수는 일급이기 때문에, 함수를 함수의 결과로도 사용할 수 있다. 이를 조합성 또는 추상화의 도구라고 부른다.
const f1 = () => () => 1
log(f1()) // () => 1
const f2 = f1()
log(f2) // () => 1
고차함수
- 값으로 다뤄질 수 있는 일급 함수의 성질을 이용해, 함수를 값으로 다루는 함수를 말한다.
- 크게 함수를 인자로 받아서 실행하는 함수와, 함수를 만들어 (=클로저를 만들어) 반환하는 함수 두 가지로 분류된다.
1️⃣ 함수를 인자로 받아서 실행하는 사례
const apply1 = f => f(1) // 함수 f를 인자로 받아 실행하는 apply1을 고차함수라고 볼 수 있다.
const add2 = a => a + 2
log(apply1(add2)) // 3
const times = (f, n) => {
let i = -1
while (++i < n) f(i)
};
times(log, 3) // 함수 f를 인자로 받아 내부에서 원하는 값을 만드는 applicative function이라고도 불린다.
2️⃣ 함수를 만들어 반환하는 사례
const addMaker = a => b => a + b
const add10 = addMaker(10)
log(add10) // b => a + b ➡️ 함수이자, 인자 a를 기억하는 클로저
log(add10(5)) // 15
log(add10(10)) // 20
함수 정의 방식
- 함수 호출 이전에 매개변수와 실행문, 반환 값을 지정하는 것을 말한다. 정의된 함수는 자바스크립트 엔진에 의해 평가되어 함수 객체가 되며, 각 정의 방식은 미묘하지만 중요한 차이점이 존재한다.
1️⃣ 함수 선언문
function add(x, y) {
return x + y
}
- 함수 리터럴과 동일한 형태를 갖는다. 단, 함수 선언문은 함수 이름을 생략할 수 없다는 차이점이 있다.
- 함수 선언문은 표현식이 아닌 문이다. 이를 실행하면 완료 값 undefined가 출력된다. 만약 표현식인 문이라면, 표현식이 평가되어 생성된 함수가 출력되어야 한다.
- 일반적으로 표현식이 아닌 문은 변수에 할당될 수 없지만, 자바스크립트 엔진이 함수 리터럴 표현식으로 해석하는 경우 변수에 할당되는 것처럼 보일 수 있다 ➡️ 자바스크립트 엔진은 생성된 함수를 호출하기 위해 함수 이름과 동일한 이름의 식별자를 암묵적으로 생성하고, 거기에 함수 객체를 할당한다. (함수 표현식으로의 변환으로 볼 수 있음)
2️⃣ 함수 표현식
const add = function foo (x, y) {
return x + y
}
log(foo) // ReferenceError ➡️ 함수 몸체 내부에서만 유효한 식별자이기 때문
log(add(2,6)) // 8
- 선언한 함수에 대한 식별자를 직접 생성해 함수 객체를 할당한다.
- 자체적으로 식별자를 생성하는 함수 선언식과 유사해 보이지만, '표현식이 아닌 문'과 '표현식인 문'에서의 차이가 있다.
- 함수 생성 시점에서도 차이점이 존재한다.
3️⃣ Function 생성자 함수
const add = new Function('x', 'y', 'return x + y')
- 보기만 해도 뭔가 쓰기 꺼려지는 문법이다. 위의 방식으로 생성된 함수는 클로저를 생성하지 않는 등의 차이점이 존재한다.
4️⃣ 화살표 함수(ES6)
const add = (x, y) => x + y
- 화살표 함수는 항상 익명 함수로 정의한다.
- 기존의 함수보다 표현이 간략할 뿐 아니라 내부 동작 방식 또한 간략화되어 있다.
- 생성자 함수로 사용할 수 없으며, this 바인딩 방식이나 prototype 프로퍼티의 유무 등의 차이가 존재한다.
더 공부할 내용
- 표현식인 문과 표현식이 아닌 문 (모딥다 5.6)
- 화살표 함수 (모딥다 26.3)