해결된 질문
작성
·
52
0
배열 생성자로 배열 선언시, undefined로 출력 되는 것이 아니라 empty로 출력이 되는데, empty와 undefined는 다른 것으로 판단됩니다. 결국 비어있는 배열에 접근할 경우 자바스크립트 엔진에서 undefined로 인식하니까 결국 같은 것으로 생각해야 할까요
답변 2
0
안녕하세요. 807연구실님! 질문 주셔서 감사합니다.
먼저 평일에는 제가 답변을 빨리 못 드리는 점 양해 부탁드립니다.
배열 생성자로 생성시 empty 와 undefined 에 관해서 질문 주셨는데요. 먼저 답변을 드리면, empty 와 undefined 는 서로 다른 것입니다.
자바스크립트에서 undefined 는 엄연한 값입니다. 강의 중에 V8은 undefined, null 그리고 string 을 어떻게 관리할까 편을 보시면, undefined 가 어떻게 생성되고 관리되는지 아실 수 있습니다.
그렇다면 배열을 생성자로 생성시 empty 는 무엇인지 좀 더 알아 보겠습니다.
자바스크립트로 배열 생성할 때, 우리는 꽉 찬 배열과 구멍이 존재하는 배열을 생성할 수 있습니다.
// 꽉 찬 배열
const array = [1, 2, 3];
// 구멍이 있는 배열, 일명 Sparse Array
const array = new Array(3);
Sparse Array 는 모든 인덱스에 할당 된 값이 없을 수 있는 배열을 말합니다. 즉, 구멍이 있는 배열이죠. 예를 들어, 1번 인덱스에 값이 없는 배열은 아래와 같습니다.
[0, ,2]
위 표기법에서 값이 할당되지 않았다는 것을 표시하기 위해서 자바스크립트는 empty 를 사용합니다.
[0, empty, 2]
이와 다르게, 아래 배열은 1번 인덱스에 undefined 라는 값을 가지고 있는 것입니다.
[0, undefined, 2]
즉, 자바스크립트에서 값이 있다는 것은 메모리를 할당 받았다는 것을 의미하기 때문에 empty 는 메모리를 할당 받지 않은 것(배열의 슬롯)을 의미합니다.
중요한 것은 왜 이렇게 되어야 했을까를 이해하는 것입니다.
사실 자바스크립트 배열은 객체입니다. 우리가 흔히 아래처럼 객체 리터럴로 표시하는 바로 그 객체입니다.
const obj = {};
[1, 2, 3]
을 객체로 표현하면 아래와 같습니다.
const arrayObj = {
0: 1,
1: 2,
2: 3
}
즉, 인덱스를 속성키 이름으로 갖는 객체입니다. 그래서 아래와 같이 접근 가능합니다.
arrayObj[0] // 1 입니다.
arrayObj[1] // 2 입니다.
arrayObj[2] // 3 입니다.
여기에 추가로 length 라는 속성을 추가하면 자바스크립트에서 배열과 비슷한 객체라고 해서 array-like object 를 만들 수 있습니다.
const arrayLikeObj = {
0: 1,
1: 2,
2: 3,
length: 3
}
array-like object 는 특별한 것이 없지만, Array.from 등을 통해서 Array 객체로 쉽게 변환할 수 있습니다.
Array.from은 첫 번째 인자로, iterable 또는 arrayLike 객체를 받아서 배열로 반환합니다.
그래서 아래와 같이 하면 빈 배열이 반환됩니다.
Array.from({
0: 1,
1: 2,
2: 3,
})
// [] 이 반환됩니다.
하지만 length 를 추가하면 [1, 2, 3]
배열이 반환됩니다.
Array.from({
0: 1,
1: 2,
2: 3,
length: 3
});
// [1, 2, 3] 이 반환됩니다.
대표적인 Array Like 객체가 function 객체의 arguments 입니다. function 함수 객체가 받는 인자를 Array Like 객체 형태로 담고 있습니다. 그리고 document 의 querySelectorAll 이 반환하는 NodeList 도 Array Like 객체입니다.
const nodeList = document.querySelectorAll('div');
Array.isArray(nodeList); // false
'length' in nodeList; // true
이렇듯 자바스크립트는 객체를 사용해 배열을 표현합니다. C언어와 같은 언어에서는 연속적인 메모리 블럭이 배열인 것과 다른 점입니다.
그렇다면, 자바스크립트에서 배열이 왜 sparse array 즉, 구멍이 존재할 수 있는 배열인지 이해할 수 있습니다.
아래와 같이 배열을 생성해 봅시다.
const bigArray = new Array(1000000000);
10억 개입니다. 참고로 배열 생성자로 생성할 수 있는 최대 길이는 2^32 - 1 개입니다. 배열이 길이가 32비트 부호 없는 정수로 표현되기 때문입니다. 배열 생성자로 10억개를 생성할 때, 모든 원소에 대해서 메모리를 할당하면 어떻게 될까요? 1개의 원소가 1byte 만 차지해도 0.9 GB 로 약 1GB 의 메모리를 사용하게 됩니다.
const bigArray = {
0: 어떤값,
1: ...
...
999999999: 어떤값
}
자바스크립트는 태생이 브라우저 안에서 실행되는 작은 스크립트 언어였습니다. 즉, 브라우저의 프로세스 내부에서 실행되는 것이었죠. 자바스크립트가 위처럼 크게 메모리를 할당하면, 브라우저가 뻗거나 꺼지거나 하는 일이 발생할 것입니다.
그리고 메모리 할당과 해제를 해야하기 때문에 브라우저의 속도가 매우 느려졌을 것입니다. 그리고 자바스크립트는 꽤 오래전에 탄생한 언어이기 때문에, 그 당시 PC는 메모리가 충분하지 않았습니다.
모든 배열 생성에 브라우저 프로세스에 영향을 주지 않은채 충분한 메모리를 사용하기란 불가능했을 것입니다.
그래서 자바스크립트는 객체로 배열을 표현하고, 객체의 키를 인덱스로 사용하기로 한 것입니다.
그래서 아래와 같은 일이 가능한 것입니다.
const arr = [1, 2, 3];
arr[999999999] = 10;
arr 은 아래와 같이 구멍이 존재하는 sparse array 가 되는 것이죠.
[1, 2, 3, empty × 999999996, 10]
즉, 1, 2, 3, 10 을 제외하고 다른 자리(슬롯)에는 메모리가 할당되지 않은 것을 나타내는 empty 를 표시하는 것입니다.
자 여기서 확인해 볼 내용은 위에서 생성한 arr의 길이는 몇 일까요?
arr.length
// 1000000000 입니다.
즉, arr 을 객체로 표현하면
const arr = {
0: 1,
1: 2,
2: 3,
999999999: 10,
length: 4
}
가 아니라
const arr = {
0: 1,
1: 2,
2: 3,
999999999: 10,
length: 1000000000
}
라는 점입니다. 아래 코드를 실행하면,
arr.forEach((value, i) => console.log(value, i));
1 0
2 1
3 2
까지는 빨리 출력되지만, 조금 시간이 지난 후에
10 999999999
이 출력됩니다. 즉, forEach 는 length 횟수만큼 실행하지만, empty 에 대해서는 콜백함수를 실행하지 않기 때문입니다.
만약 empty 대신 에 undefined 를 갖고 있다고 해 볼게요.
const bigArr = new Array(1000000000).fill(undefined);
위 코드를 실행해 보시면, 아래 그림처럼 브라우저가 뻗는 것을 확인할 수 있습니다. 10억개의 메모리를 할당하다가 뻗는 것이죠.
이렇게 해서 sparse array 에서 empty 와 undefined 가 서로 다르다는 것과 empty 의 의미, 그리고 sparse array 가 자바스크립트에서 필요했던 역사적인 내용 등을 같이 알아 보았습니다.
답변이 도움이 되었길 바랍니다.
감사합니다.
답변을 적고 수업을 확인해 보니 수업 중에서는 아래 코드가 undefined 로 초기화 된 배열을 출력하고 있었네요.
const fiveItems = new Array(5);
console.log(fiveItems);
// [undefined, undefined, undefined, undefined, undefined]
하지만 이는 코드샌드박스의 보정으로 아래와 같이 실행된 것과 동일합니다.
const fiveItems = new Array(5).fill(undefined);
console.log(fiveItems);
아무래도 Babel 의 트랜스파일러 영향인 것 같습니다.
만약 보정이 없다면,
const fiveItems = new Array(5);
console.log(fiveItems);
는 아래와 같이 empty 가 5개 있는 sparse array 가 되어야 합니다.
[empty x 5]
혼란을 드린 점 죄송합니다. 관련 정정 내용은 수업 노트로 추가하였습니다.
감사합니다.
0
안녕하세요, 인프런 AI 인턴입니다. 807연구실님!
배열 생성자로 배열을 생성 시 empty
와 undefined
의 차이에 대해 질문해 주셨습니다.
자바스크립트에서 배열의 경우 ‘빈 슬롯’(empty slot)과 ‘undefined’는 분명히 다릅니다. 빈 슬롯은 배열에 공간은 있지만, 그 공간에 값이 할당되지 않았음을 의미합니다. 예를 들어 new Array(5)
를 사용하면 길이가 5인 배열이 만들어지는데, 각 요소가 “비어있는 상태”로 초기화됩니다. 따라서 console.log()
결과를 보면 [empty × 5]
로 표시되는 것이죠.
반면, undefined
는 변수가 선언은 되었지만, 아직 값이 할당되지 않은 상태를 나타냅니다. 즉, 배열에 특정 값을 명시적으로 설정하면 그 값이 없을 때 undefined
를 출력할 수 있습니다.
두 상태의 차이는 다음과 같습니다:
- 빈 슬롯 (empty slot): 실제로 존재하는 ‘비어있는’ 자리를 나타내며 배열의 길이에 포함됩니다. 하지만 배열 메소드나 루프에서 건너뛰어질 수 있습니다.
- undefined: 정확히 자리와 값이 있는 배열 요소로서 명시적으로 할당되지 않은 상태를 나타내며, 배열 메소드나 루프를 통해 접근 가능하며 출력될 수 있습니다.
배열의 빈 슬롯에 대해 이해를 돕기 위한 유사한 질문 링크는 아래에서 참고하실 수 있습니다:
이와 관련된 자바스크립트 강의를 통해서 더 깊은 이해를 얻으실 수 있습니다.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.
자세한 설명 감사합니다. 한 번에 완벽하게 이해하기 어려워서 계속 반복해서 보겠습니다.