함수가 호출되면 함수의 매개변수, 반환 주소값, 지역 변수 등의 스택 프레임(Stack Frame)이 호출 스택(Call Stack)에 쌓이게 된다. 재귀함수나 콜백함수에 의해서 함수가 종료되지 않고 너무 많이 호출되면 이러한 스택 프레임들이 호출 스택의 메모리를 초과하게 되면 스택 오버플로우(Stack Overflow)가 발생한다.
함수의 호출이 너무 많아서 스택 오버플로우가 일어날 수도 있지만, 함수를 한 번만 호출했는데 매개변수가 너무 많아서 스택 오버플로우가 발생할 수도 있다. 함수의 매개변수도 호출 스택에 쌓이기 때문이다.
const arr = new Array(1000000);
const arr2 = [...arr];
위의 코드에서 length가 1000000인 배열 arr를 스프레드 연산자(...)를 활용하여 arr2에 복사하였다.
그러나 위 코드를 아래와 같이 바꾸면 RangeError가 발생한다.
const arr = new Array(1000000);
const arr2 = [];
arr2.push(...arr); // Uncaught RangeError: Maximum call stack size exceeded
push라는 함수의 매개변수로 인수를 1,000,000개나 전달했기 때문이다.
const doNothing = function (...args) {};
const arr = new Array(1000000);
doNothing(...arr); // Uncaught RangeError: Maximum call stack size exceeded
Rest 파라미터(나머지 매개변수)를 사용하면 가변 인자 함수를 만들 수 있는데, 이 경우에 너무 많은 인수를 넣어 함수를 호출하면 스택 오버플로우가 발생하게 된다.
const doNothing = function (...args) {};
const arr = new Array(1000000);
doNothing.apply(null, arr); // Uncaught RangeError: Maximum call stack size exceeded
인수 리스트를 배열이나 유사 배열 객체(array-like objects)로 받아 함수에게 전달하는 Function.prototype.apply 또한 너무 많은 인수를 전달하면 동일한 문제가 발생한다.
스택 오버플로우를 피하기 위해서는 "한 번에" 너무 많은 인수를 전달하지 않으면 된다.
const arr = new Array(1000000);
const arr2 = [];
for (const i of arr) arr2.push(i);
// 또는 그냥 arr2 = [...arr]
const arr = new Array(1000000).fill(1);
arr[12345] = 2;
// const maxNum = Math.max(...arr)
// Uncaught RangeError: Maximum call stack size exceeded
const maxNum = arr.reduce((acc, v) => Math.max(acc, v), arr[0]); // 2
참조
http://net-informations.com/js/err/range.htm
'IT > JavaScript' 카테고리의 다른 글
[JS] 자바스크립트로 엑셀 파일(xlsx) 만들어서 다운받기 (0) | 2022.08.05 |
---|---|
[JS] Invalid regular expression: invalid group specifier name (0) | 2022.06.21 |
[JS] Selection API로 선택된 텍스트 정보 가져오기 (0) | 2022.06.01 |
[JS] 자바스크립트의 배열 생성 방법 (0) | 2021.07.29 |
Node.js로 백준(BOJ) 문제 풀 때 유의할 점들 (12) | 2021.04.10 |