재귀와 스택 https://ko.javascript.info/recursion
function pow(x, n) {
if (n == 1) {
return x;
} else {
return x * pow(x, n - 1);
}
}
alert( pow(2, 3) ); // 8
pow (2, 4)를 계산하려면 아래와 같은 재귀 단계가 차례대로 이어진다.
실행 중인 함수의 실행 절차에 대한 정보는 해당 함수의 실행 컨텍스트(execution context) 에 저장된다.
실행 컨텍스트는 함수 실행에 대한 세부 정보를 담고 있는 내부 데이터 구조로 제어 흐름의 현재 위치, 변수의 현재 값, this의 값 등 상세 내부 정보가 실행 컨텍스트에 저장된다.
함수 호출 일 회당 정확히 하나의 실행 컨텍스트가 생성된다.
함수 내부에 중첩 호출이 있을 때는 아래와 같은 절차가 수행된다.
하지만 배열은 요소 '삭제’와 '삽입’에 들어가는 비용이 많이 든다.
빠르게 삽입 혹은 삭제를 해야 할 때는 배열 대신 연결 리스트(linked list)라 불리는 자료 구조를 사용할 수 있다.
연결 리스트 요소는 value, next 프로퍼티를 사용하여 정의할 수 있다.
next는 다음 연결 리스트 요소를 참조하는 프로퍼티로 다음 요소가 없을 땐 null이 된다.
let list = {
value: 1,
next: {
value: 2,
next: {
value: 3,
next: {
value: 4,
next: null
}
}
}
};
// 아래처럼 작성할 수도 있다.
let list = { value: 1 };
list.next = { value: 2 };
list.next.next = { value: 3 };
list.next.next.next = { value: 4 };
list.next.next.next.next = null;
연결 리스트를 사용하면 전체 리스트를 여러 부분으로 쉽게 나눌 수 있고, 다시 합치는 것도 가능하다. 요소를 쉽게 추가하거나 삭제할 수도 있다.
//나누기
let secondList = list.next.next;
list.next.next = null; // list는 1->2->null, secondList는 3->4->null
//합치기
list.next.next = secondList;
//list에 새로운 value 추가
let list = { value: 1 };
list.next = { value: 2 };
list.next.next = { value: 3 };
list.next.next.next = { value: 4 };
list = { value: "new item", next: list };
//list에 'new item'이 들어가고 next는 기존 list값인 1이 된다.
//중간 요소 제거하려면 이전 요소의 next를 변경해주면 된다.
list.next = list.next.next; //list(='new item')의 next(=1)에 next의 next(=2)를 넣음
위 예시의 마지막 예문에서 변경된 next인 1은 체인에서 제외되어 다른 곳에 따로 저장되지 않으면 메모리에서 제거된다.