함수 내부에서 자기 자신을 호출하는 함수.
재귀함수를 활용하면 문제를 더 작고 해결 가능한 하위 문제로 분할할 수 있기 때문에 보다 직관적이고 간결하게 표현할 수 있다.
function eatBreakfast(){
let meal = cookFood();
return `Eating ${meal}`
}
function cookFood(){
let items = ['Meat', 'Egg', "Bread"];
return items[Math.floor(Math.random()*items.length)];
}
function wakeUp(){
eatBreakfast();
console.log("Ok ready to go");
}
wakeUp();
function countDown(num){
if(num <= 0){
console.log('done');
return;
}
console.log(num);
num--;
countDown(num)
}
countDown(5);
요약하자면, 일반 함수는 호출 스택에 함수 정보가 추가되고 제거되는 단순한 방식으로 동작하지만, 재귀 함수는 재귀 호출에 따라 호출 스택에 새로운 함수 정보가 추가되고 제거되는 방식으로 동작한다.
function sumRange(num){
if(num === 1) return 1;
return num + sumRange(num - 1);
}
sumRange(3);
sumRange(3) 호출
| sumRange(3) |
3 + sumRange(2) 실행, sumRange(2) 호출
| sumRange(2) |
| sumRange(3) |
2 + sumRange(1)를 실행, sumRange(1) 호출
| sumRange(1) |
| sumRange(2) |
| sumRange(3) |
sumRange(1)이 1을 반환, call stack 제거
| sumRange(2) |
| sumRange(3) |
sumRange(2)는 sumRange(1)의 반환 값을 받아 2 + 1을 반환, callstack 제거
| sumRange(3) |
sumRange(3)은 sumRange(2)의 반환 값을 받아 3 + 3을 반환, callstack 제거
| (empty) |
함수가 호출된 이후에도 변수가 값을 유지하게 하는 방법!
함수 위에 let result = [] 같이 뜬금없는 변수를 배치하는 대신, 헬퍼 메소드 재귀를 사용해서 전체를 감싸준다.
function collectOddValues(arr){
let result = [];
function helper(input){
if(input.length === 0){ // 종료 조건
return;
}
if( input[0] % 2 !== 0){
result.push(input[0]);
}
helper(input.slice(1));
}
helper(arr);
return result;
}
collectOddValues([1,2,3,4,5,6])
모든 코드가 함수 자체에 포함되며 재귀적.
function collectOddValues(arr){
let newArr = []; // 매 재귀 실행마다 리셋
if(arr.length === 0){
return newArr;
}
if(arr[0] % 2 !== 0){
newArr.push(arr[0]);
}
newArr = newArr.concat(collectOddValues(arr.slice(1)));
return newArr;
}