재귀
: 함수가 자기 자신을 호출하는 것
: 큰 목표 작업 하나를 동일하면서 간단한 작업 여러 개로 나눌 때 유용한 프로그래밍 패턴
function pow(x, n) {
let result = 1;
// 반복문을 돌면서 x를 n번 곱함
for (let i = 0; i < n; i++) {
result *= x;
}
return result;
}
alert( pow(2, 3) ); // 8
재귀깊이
function pow(x, n) {
return (n == 1) ? x : (x * pow(x, n - 1));
}
: 가장 처음 시행하는 호출을 포함한 중첩 호출의 최대 개수
: pow (x, n)의 재귀 깊이는 n
실행컨텍스트
: 함수 실행에 대한 세부 정보를 담고 있는 내부 데이터 구조
: 실행 중인 함수의 실행 절차에 대한 정보가 저장 되는 자료구조
: 제어 흐름의 현재 위치, 변수의 현재 값, this의 값 등 상세 내부 정보가 저장 됨
: 함수 호출 1회당 정확히 하나의 실행 컨텍스트가 생성 됨
- 함수 내부에 중첩 호출이 있을 경우의 절차
: 현재 함수의 실행이 일시중지
: 중지된 함수와 연관된 실행 컨텍스트는 실행 컨텍스트 스택 이라는 자료구조에 저장
: 중첩 호출 실행
: 중첩 호출이 끝난 뒤 실행 컨텍스트 스택에서 일시 중단한 함수의 실행 컨텍스트를 꺼내오고
중단한 함수의 실행을 다시 진행
재귀적 순회
let company = { // 동일한 객체(간결성을 위해 약간 압축함)
sales: [{name: 'John', salary: 1000}, {name: 'Alice', salary: 1600 }],
development: {
sites: [{name: 'Peter', salary: 2000}, {name: 'Alex', salary: 1800 }],
internals: [{name: 'Jack', salary: 1300}]
}
};
// 급여 합계를 구해주는 함수
function sumSalaries(department) {
if (Array.isArray(department)) { // 첫 번째 경우
return department.reduce((prev, current) => prev + current.salary, 0); // 배열의 요소를 합함
} else { // 두 번째 경우
let sum = 0;
for (let subdep of Object.values(department)) {
sum += sumSalaries(subdep); // 재귀 호출로 각 하위 부서 임직원의 급여 총합을 구함
}
return sum;
}
}
alert(sumSalaries(company)); // 7700
: 재귀적 순회를 구현한 예시
: 모든 임직원의 급여를 더한 값을 출력
연결리스트 구조
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;
: 재귀적으로 정의된 자료구조는 자기 자신을 이용해 자료 구조를 정의
나머지 매개변수 ...
: 자바스크립트에서는 함수 정의와 상관없이 함수에 넘겨주는 인수의 개수에 제약이 없음
: 함수를 정의할 때 인수를 2개만 받도록 하고 실제 함수를 호출 할 때 더 많은 인수를
전달해도 오류가 발생하지 않음
: 그러나 가장 앞 2개의 인수만 사용됨
: ... 을 사용하면 모든 인수를 전달할 수 있음
- ...
: 남은 매개변수들을 모아 배열로 반환함을 의미하는 문법
: 나머지 매개변수는 항상 마지막에 존재해야 함
function sum(a, b) {
return a + b;
}
alert( sum(1, 2, 3, 4, 5) );
function sumAll(...args) { // args는 배열의 이름입니다.
let sum = 0;
for (let arg of args) sum += arg;
return sum;
}
alert( sumAll(1) ); // 1
alert( sumAll(1, 2) ); // 3
alert( sumAll(1, 2, 3) ); // 6
arguments 객체
: 인덱스를 사용해 인수에 접근할 수 있도록 하는 유사 배열 객체
: 오래된 코드에서 사용되던 문법
: 배열 메서드를 사용할 수 없다는 단점
: 인수 전체를 담기 때문에 나머지 매개변수 처럼 인수의 일부만 사용하는 것도 불가
function showName() {
alert( arguments.length );
alert( arguments[0] );
alert( arguments[1] );
// arguments는 이터러블 객체이기 때문에
// for(let arg of arguments) alert(arg); 를 사용해 인수를 펼칠 수 있습니다.
}
// 2, Bora, Lee가 출력됨
showName("Bora", "Lee");
// 1, Bora, undefined가 출력됨(두 번째 인수는 없음)
showName("Bora");
스프레드 문법
: 배열을 통째로 매개변수에 넘기는 방법
let arr = [3, 5, 1];
alert( Math.max(arr) ); // NaN
alert( Math.max(...arr) ); // 5
let arr1 = [1, -2, 3, 4];
let arr2 = [8, 3, -8, 1];
alert( Math.max(...arr1, ...arr2) ); // 8
let arr1 = [1, -2, 3, 4];
let arr2 = [8, 3, -8, 1];
alert( Math.max(1, ...arr1, 2, ...arr2, 25) ); // 25
let arr = [3, 5, 1];
let arr2 = [8, 9, 15];
let merged = [0, ...arr, 2, ...arr2];
alert(merged); // 0,3,5,1,2,8,9,15 (0, arr, 2, arr2 순서로 합쳐집니다.)
let str = "Hello";
alert( [...str] ); // H,e,l,l,o
// Array.from은 이터러블을 배열로 바꿔줍니다.
alert( Array.from(str) ); // H,e,l,l,o
: 문자열, 배열의 요소를 나누어서 반환
: 이터러블 객체에만 사용가능
: 문자열을 객체로 바꿀 때는 유사 배열 객체 및 이터러블 객체까지 지원하는 Array.from을 주로 이용
스프레드를 이용한 객체 복사
let obj = { a: 1, b: 2, c: 3 };
let objCopy = { ...obj }; // 객체를 펼쳐서 각 요소를 분리후, 매개변수 목록으로 만든 다음에
// 매개변수 목록을 새로운 객체에 할당함
// 객체 복사본의 프로퍼티들이 기존 객체의 프로퍼티들과 진짜 같을까요?
alert(JSON.stringify(obj) === JSON.stringify(objCopy)); // true
// 두 객체는 같을까요?
alert(obj === objCopy); // false (참조가 다름)
// 참조가 다르므로 기존 객체를 수정해도 복사본은 영향을 받지 않습니다.
obj.d = 4;
alert(JSON.stringify(obj)); // {"a":1,"b":2,"c":3,"d":4}
alert(JSON.stringify(objCopy)); // {"a":1,"b":2,"c":3}
Refference
'Programming > JavaScript' 카테고리의 다른 글
모던 자바스크립트 (함수) 4-3. 전역 객체 / 함수 표현식 / new Function 문법 (0) | 2022.04.23 |
---|---|
모던 자바스크립트 (함수) 4-2. 변수의 유효범위와 클로저 / var (0) | 2022.04.21 |
javascript의 데이터를 멋있게 다루는 방법에 대한 총 정리. (filter / find / reduce / map / forEach /new Map / new Set / lodash / regex) (0) | 2022.04.19 |
자바스크립트 배열의 요소 삭제하기 (0) | 2022.04.19 |
자바스크립트 reduce 함수 총 정리 (0) | 2022.04.19 |