JavaScript / 배열 length 속성과 길이 변경 시 주의점
Array.length는 배열의 슬롯 수를 나타내는 속성입니다. 일반적인 연속 배열에서는 요소 수와 같지만, 중간이 빈 희소 배열에서는 실제 값이 있는 자리 수보다 클 수 있습니다. 인덱스가 커지거나 length에 값을 직접 대입하면 길이와 배열 내용이 함께 바뀝니다.
length와 마지막 인덱스의 관계
배열 인덱스는 0부터 시작하므로 값이 4개 연속 들어 있는 배열의 마지막 인덱스는 3이고 길이는 4입니다. 비어 있는 배열은 길이가 0이며 마지막 요소가 없습니다. length는 메서드가 아니므로 괄호 없이 읽습니다.
const colors = ['red', 'green', 'blue', 'black'];
console.log(colors.length); // 4
console.log(colors[colors.length - 1]); // 'black'
console.log([].length); // 0
마지막 값을 읽을 때는 배열이 비어 있지 않은지 확인하세요. 빈 배열에서 items[items.length - 1]은 items[-1]을 읽으므로 undefined가 나옵니다. 배열의 값이 연속이라는 전제가 없으면 길이를 ‘값이 있는 요소 개수’라고 설명하면 정확하지 않습니다.
비어 있는 슬롯이 있는 배열
큰 인덱스에 값을 대입하면 그 앞의 비어 있는 위치까지 포함하는 길이가 됩니다. 예를 들어 인덱스 10에 처음 값을 넣으면 길이는 11입니다. 하지만 그 배열에 실제로 값이 있는 자체 인덱스는 하나뿐입니다.
const items = [];
items[10] = 'X';
console.log(items.length); // 11
console.log(Object.keys(items)); // ['10']
console.log(0 in items); // false
console.log(10 in items); // true
비어 있는 슬롯을 읽으면 undefined가 나와도, 명시적으로 저장한 undefined와 같은 구조는 아닙니다. 0 in items처럼 그 인덱스가 존재하는지 검사하면 구분할 수 있습니다. Object.keys()는 값이 있는 열거 가능한 인덱스를 보여 주지만, 일반적인 배열에서 추가한 문자열 이름 속성까지 포함할 수 있으므로 모든 배열의 “요소 수”를 세는 만능 방법으로 보지 마세요.
length에 직접 값을 대입할 때
length를 줄이면 새 길이 밖의 요소가 삭제됩니다. 다시 길이를 늘려도 삭제한 값은 돌아오지 않습니다. 길이를 키우면 새로 생긴 자리는 undefined 값이 채워진 것이 아니라 빈 슬롯입니다.
const letters = ['A', 'B', 'C', 'D'];
letters.length = 2;
console.log(letters); // ['A', 'B']
letters.length = 4;
console.log(letters.length); // 4
console.log(2 in letters); // false: 'C'가 되살아나지 않음
음수나 소수처럼 유효하지 않은 길이를 대입하면 RangeError가 발생합니다. 데이터를 버리려는 의도가 없다면 길이를 줄이기 전에 배열을 복사하세요. MDN의 Array.length 문서에 허용 범위와 빈 슬롯 동작이 정리되어 있습니다.
전체 예제: 길이와 실제 자리 비교하기
아래 코드를 UTF-8로 array-length.html에 저장해 브라우저에서 엽니다. 인덱스 10에 값을 넣어 길이와 실제 인덱스 수가 달라지는 것을 보고, 길이를 줄였다가 다시 늘려 값이 복구되지 않는지 확인하세요. ‘처음으로’는 새 배열을 만들어 원래 상태를 복원합니다.
<!doctype html>
<html lang="ko">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Array.length 값과 빈 슬롯 확인</title>
</head>
<body>
<button id="add" type="button">인덱스 10에 X 넣기</button>
<button id="shorten" type="button">길이를 3으로 줄이기</button>
<button id="extend" type="button">길이를 7로 늘리기</button>
<button id="reset" type="button">처음으로</button>
<pre id="output" aria-live="polite"></pre>
<script>
let items = ['A', 'B', 'C'];
const output = document.querySelector('#output');
function show() {
const keys = Object.keys(items);
output.textContent = `length: ${items.length}\n` +
`값이 있는 인덱스: ${keys.length ? keys.join(', ') : '(없음)'}\n` +
`값이 있는 항목: ${keys.map(key => `${key}:${items[key]}`).join(', ') || '(없음)'}`;
}
document.querySelector('#add').addEventListener('click', () => {
items[10] = 'X';
show();
});
document.querySelector('#shorten').addEventListener('click', () => {
items.length = 3;
show();
});
document.querySelector('#extend').addEventListener('click', () => {
items.length = 7;
show();
});
document.querySelector('#reset').addEventListener('click', () => {
items = ['A', 'B', 'C'];
show();
});
show();
</script>
</body>
</html>
처음에는 길이 3, 인덱스 0, 1, 2가 보입니다. ‘인덱스 10에 X 넣기’를 누르면 길이는 11이고 인덱스는 0, 1, 2, 10입니다. 길이를 3으로 줄이면 10번 값이 삭제되고, 다시 7로 늘려도 인덱스는 0, 1, 2만 남습니다. 이 결과로 length와 실제로 채워진 자리 수를 구분할 수 있습니다.




