모던 JavaScript 튜토리얼을 따라가면서 정리합니다.
순서가 있는 컬렉션을 다뤄야할 때 객체를 사용하면 순서와 관련된 메서드가 없어 편리하지 않다. 객체는 순서를 고려하지 않고 만들어진 자료구조이기 때문이다. 따라서 객체를 이용하면 새로운 프로퍼티를 기존 프로퍼티 ‘사이에’ 끼워넣는 것도 불가능하다.
배열은 특수한 형태의 객체이다.
순서가 있는 자료를 저장하고 관리하는 용도에 최적화되어 있다.
선언 방법
1 2
let arr = [item1, item2...]; // 가장 많이 사용됨 let arr = new Array(item1, item2...);
new Array(number)
를 호출하면 길이가number
인 배열이 만들어진다.length
프로퍼티는 배열의 길이를 나타내준다. 배열 메서드는length
프로퍼티를 자동으로 조절해준다.length
값을 수동으로 줄이면 배열 끝이 잘린다.배열을 데큐처럼 사용하기
push(...items)
:items
를 배열 끝에 넣어준다.pop()
: 배열 끝 요소를 제거하고, 제거한 요소를 반환한다.shift()
: 배열 처음 요소를 제거하고, 제거한 요소를 반환한다.unshift(...items)
:items
를 배열 처음에 더해준다.
배열의 내부 동작 원리
- 배열은 키가 숫자라는 점만 다른 특별한 종류의 객체이다.
- 숫자형 키를 사용함으로써 배열은 객체 기본 기능 이외에도 순서가 있는 컬렉션을 제어하게 해주는 특별한 메서드와
length
같은 프로퍼티도 제공한다. - 자바스크립트 엔진은 배열의 요소를 인접한 메모리 공간에 차례로 저장해 연산 속도를 높인다.
- 배열은 객체이므로 원하는 프로퍼티를 추가해도 문제가 발생하지 않는다. 그러나 이러면 자바스크립트 엔진이 배열을 일반 객체처럼 다루게 되어 배열을 다룰 때만 적용되는 최적화 기법이 동작하지 않아 배열 특유의 이점이 사라진다.
성능
push
와pop
은 빠르지만shift
와unshift
는 느리다. 제거하거나 추가할 뿐만 아니라 이를 위해 다른 요소들을 이동해야 하기 때문이다. 배열에 요소가 많으면 요소가 이동하는 데 걸리는 시간이 길고 메모리 관련 연산도 많아진다.pop
과push
의 경우 요소 이동을 수반하지 않는다.모든 요소를 대상으로 반복 작업하기
for (let i = 0; i < arr.length; i++)
: 가장 빠른 방법, 오래된 브라우저와 호환 가능for (let item of arr)
: 배열 요소에만 사용되는 모던한 문법for (let item in arr)
: 배열엔 사용하지 말자!모든 프로퍼티를 대상으로 순회한다.
유사 배열(array-like) 객체의 경우 배열과는 달리 키가 숫자형이 아닌 프로퍼티와 메서드가 있을 수 있다. 따라서
for...in
을 사용하면 필요 없는 프로퍼티들까지 순회가 이루어지고, 문제를 일으킬 수 있다.배열이 아니라 객체와 함께 사용할 때 최적화되어 있어 속도가 느리다.
과제
배열과 관련된 연산
- 요소 “Jazz”, “Blues”가 있는
styles
배열을 생성합니다. - “Rock-n-Roll”을 배열 끝에 추가합니다.
- 배열 정 중앙에 있는 요소를 “Classics”로 바꿉니다. 가운데 요소를 찾는 코드는 요소가 홀수 개인 배열에서도 잘 작동해야 합니다.
- 배열의 첫 번째 요소를 꺼내서 출력합니다.
- “Rap”과 “Reggae”를 배열의 앞에 추가합니다.
1 2 3 4 5
Jazz, Blues Jazz, Blues, Rock-n-Roll Jazz, Classics, Rock-n-Roll Classics, Rock-n-Roll Rap, Reggae, Classics, Rock-n-Roll
답
1 2 3 4 5
let styles = ["Jazz", "Blues"]; styles.push("Rock-n-Roll"); styles[Math.floor(styles.length - 1) / 2] = "Classics"; alert(styles.shift()); styles.unshift("Rap", "Reggae");
- 요소 “Jazz”, “Blues”가 있는
배열 컨텍스트에서 함수 호출하기
1 2 3 4 5 6 7
let arr = ["a", "b"]; arr.push(function() { alert( this ); }) arr[2](); // a, b, function() { alert( this )}
입력한 숫자의 합 구하기
아래 조건을 만족하는 함수
sumInput()
을 작성해 봅시다.prompt
창을 띄워 사용자에게 숫자를 입력해 달라고 요청한 후, 입력받은 값들을 배열에 저장합니다.- 숫자가 아닌 값, 혹은 빈 문자열을 입력하거나 ‘Cancel’ 버튼을 누르면 질문을 멈춥니다.
- 배열 요소의 합을 계산하고 리턴합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
function sumInput() { let numbers = []; while (true) { let response = prompt("숫자를 입력해주세요."); if (response === "" || response === null || !isFinite(response)) break; numbers.push(+response); } let sum = 0; for (let number of numbers) { sum += number; } return sum; }
최대합 부분배열
인접한 요소의 총합이 최대인 arr의 부분배열을 찾아 그 요소들의 합을 리턴하는 함수
getMaxSubSum(arr)
을 작성해봅니다.1 2 3 4 5 6
getMaxSubSum([-1, 2, 3, -9]) == 5 (강조 표시된 요소들의 합) getMaxSubSum([2, -1, 2, 3, -9]) == 6 getMaxSubSum([-1, 2, 3, -9, 11]) == 11 getMaxSubSum([-2, -1, 1, 2]) == 3 getMaxSubSum([100, -9, 2, -3, 5]) == 100 getMaxSubSum([1, 2, 3]) == 6 (모든 요소)
요소 전체가 음수라면 아무런 요소도 선택하지 않아야 최댓값이 된다. 그리고 합은 0이 된다.
1
getMaxSubSum([-1, -2, -3]) = 0;
답
1 2 3 4 5 6 7 8 9 10 11
function getMaxSubSum(arr) { let maxSum = 0; let partSum = 0; for (let item of arr) { partSum += item; maxSum = Math.max(maxSum, partSum); if (partSum < 0) partSum = 0; } return maxSum; }