Skip to content
This page has been auto-translated and may contain errors.View in English

배열

docs.scrimba.com

장바구니, 성적 목록, 단체 채팅방에 있는 모든 사람의 이름을 다뤄야 하는 상황을 생각해봅시다. 변수 하나에는 값 하나만 담기기 때문에, 이런 목록을 이 방식으로 저장하면 price1, price2, price3처럼 이름이 따로따로 늘어나기만 하고, 이를 반복 처리하거나 개수를 물어볼 깔끔한 방법이 없습니다. 배열이 바로 이 문제를 해결해줍니다. 배열은 여러 값을 순서대로 하나의 이름 아래 담아두며, 자기 길이를 스스로 알고 있어서 값을 추가하고, 원하는 항목을 읽고, 전체를 몇 줄로 순회할 수 있습니다.

배열 만들고 읽기

**배열**은 값들을 순서대로 담은 목록입니다. 대괄호를 사용해서 만들며, 값은 쉼표로 구분합니다:

js
const prices = [4, 9, 2, 7];

이건 prices라는 변수 하나에 숫자 네 개가 담긴 것입니다. 하나의 값을 읽으려면 그 위치, 즉 인덱스를 대괄호에 넣어 사용합니다. 처음 배우는 사람들이 거의 다 걸려 넘어지는 부분이 있는데, 개수는 0부터 셉니다, 1부터가 아닙니다.

js
const names = ["마라", "쿠아메", "유키"];
console.log(names[0]); // 마라
console.log(names[1]); // 쿠아메

배열에 항목이 몇 개 있는지 알려면 .length를 사용합니다:

js
console.log(names.length); // 3

0부터 세기 때문에 마지막 항목은 length가 아니라 length - 1에 있습니다. 그래서 여기서 마지막 이름은 names[2]이고, names[3]은 범위를 벗어난 값입니다.

**배열**은 하나의 이름 아래 순서를 갖고 모여 있는 값들의 모음입니다. 대괄호 리터럴로 만들고, 각 항목은 인덱스, 즉 0부터 세는 위치로 읽습니다:

js
const prices = [4, 9, 2, 7];
console.log(prices[0]); // 4
console.log(prices[2]); // 2

0부터 시작하는 인덱싱은 초보 시절 겪는 대부분의 "하나 차이" 버그의 원인이므로, 지금 확실히 익혀두는 게 좋습니다. 첫 번째 항목은 인덱스 0에 있고, 마지막 항목은 length - 1에 있습니다.

js
console.log(prices.length); // 4
console.log(prices[prices.length - 1]); // 7, 마지막 항목

존재하지 않는 인덱스를 읽어도 에러가 발생하지 않습니다. prices[10]은 "여기에는 아무것도 없다"는 뜻인 undefined를 돌려줍니다. 이렇게 조용히 넘어가는 동작은 편리하지만 때로는 함정이 되기도 합니다. 인덱스에 오타가 있어도 요란하게 실패하는 게 아니라 그냥 undefined가 나오기 때문입니다.

**배열**은 대괄호 리터럴로 만드는, 순서가 있고 인덱스로 접근하는 컬렉션입니다. 항목은 0부터 세는 인덱스로 읽고, .length가 개수를 알려줍니다:

js
const prices = [4, 9, 2, 7];
console.log(prices[0]); // 4
console.log(prices.length); // 4
console.log(prices[prices.length - 1]); // 7, 마지막 항목

정확히 짚어둘 만한 특성이 두 가지 있습니다. 첫째, .length는 미리 정해둔 고정 크기가 아니라 현재 사용 중인 최대 인덱스를 추적하며, 항목을 추가하고 제거할 때마다 갱신됩니다. 둘째, 범위를 벗어난 읽기는 예외를 던지는 대신 undefined를 반환하므로, "하나 차이" 오류는 실수한 지점에서 예외로 드러나는 게 아니라 나중에 로직 어딘가에서 undefined가 흘러다니는 형태로 나타납니다. 실패를 요란하게 드러내고 싶다면 인덱스를 length와 직접 비교해서 검사해야 합니다.

배열은 여러 종류의 값을 섞어 담을 수도 있지만([1, "two", true]), 실제로 쓰이는 코드베이스는 거의 항상 배열 하나에 한 종류의 값만 담습니다. 배열을 읽는 모든 코드가 무엇을 기대해야 할지 알 수 있기 때문입니다. 이건 언어 규칙이 아니라 가독성을 위한 선택입니다.

Juno배열 만들고 읽기 배열은 대괄호 안에 값들을 순서대로 담아 하나의 이름 아래 둔 목록입니다. names[0]처럼 위치로 항목을 읽고, 개수는 0부터 센다는 걸 기억하세요. 그래서 첫 번째 항목은 [1]이 아니라 [0]입니다. 이 0부터 세는 방식 때문에 일주일 동안 헤맸으니, 목록이 하나씩 어긋난다면 이 부분을 먼저 확인하세요. 항목 개수는 .length로 세고, 마지막 항목은 length - 1에 있습니다.
Juno배열 만들고 읽기 배열은 하나의 이름 아래 순서 있는 목록을 담고, 항목은 0부터 세는 인덱스로 읽습니다. 마지막 항목은 length - 1에 있고, 초보 시절 대부분의 "하나 차이" 버그가 여기서 나옵니다. 끝을 넘어서 읽으면 에러 대신 undefined가 나오므로, 인덱스에 오타가 있어도 조용히 넘어갑니다. 이유 없이 값이 undefined로 나온다면 이 점을 떠올려보세요.
Juno배열 만들고 읽기 대괄호 리터럴, 0부터 시작하는 인덱스, 그리고 미리 정한 크기가 아니라 현재 사용 중인 최대 인덱스를 추적하는 .length. 범위를 벗어난 읽기는 예외를 던지는 대신 undefined를 돌려주므로, "하나 차이" 오류는 문제를 일으키기 전에 아래로 흘러 내려갑니다. 실패를 요란하게 만들고 싶다면 인덱스를 length와 직접 비교해서 검사하세요. 그리고 배열 하나에는 한 종류의 값만 담으세요. 언어가 강제해서가 아니라, 그래야 배열을 읽는 모든 사람이 그 안에 무엇이 들어 있는지 알 수 있기 때문입니다.

배열 바꾸기

배열은 원래 바뀌도록 만들어져 있습니다. 가장 많이 쓰는 두 메서드는 에서 추가하거나 제거합니다. push는 항목을 추가하고, pop은 마지막 항목을 제거합니다.

js
const cart = ["사과", "빵"];
cart.push("우유");
console.log(cart); // ["사과", "빵", "우유"]
cart.pop();
console.log(cart); // ["사과", "빵"]

짝을 이루는 메서드는 에서 작동합니다. unshift는 맨 앞에 추가하고, shift는 첫 번째 항목을 제거합니다.

js
cart.unshift("계란");
console.log(cart); // ["계란", "사과", "빵"]

인덱스에 직접 할당해서 항목을 바꿀 수도 있습니다:

js
cart[0] = "바나나";
console.log(cart); // ["바나나", "사과", "빵"]

무언가를 찾을 때는 includes가 있는지 없는지 알려주고, indexOf는 그 위치를 알려줍니다(없으면 -1을 줍니다):

js
console.log(cart.includes("사과")); // true
console.log(cart.indexOf("빵")); // 2

일찍 알아두면 좋은 게 하나 있습니다. const로 선언한 배열도 여전히 바꿀 수 있습니다. constcart라는 이름을 완전히 새로운 배열로 다시 지정하는 것만 막을 뿐이고, 그 이름이 가리키는 목록 자체는 push, pop, 인덱스 할당으로 여전히 자유롭게 바꿀 수 있습니다.

배열은 원본을 그대로 두고 바꾸는 게 아니라 그 자리에서 직접 수정하도록 만들어져 있습니다. 대부분의 작업은 양쪽 끝에서 이루어지는 두 쌍의 메서드로 처리합니다:

js
const cart = ["사과", "빵"];
cart.push("우유"); // 끝에 추가
cart.pop(); // 끝에서 제거
cart.unshift("계란"); // 앞에 추가
cart.shift(); // 앞에서 제거

pushpop은 비용이 적게 들고 자주 쓰이는 쌍이라 끊임없이 사용하게 됩니다. shiftunshift는 맨 앞을 다루는데, 이는 나머지 모든 항목이 한 칸씩 이동해야 한다는 뜻이라 큰 배열에서는 그만큼 더 많은 작업이 필요합니다. 순서를 마음대로 정할 수 있는 상황이라면 끝 쪽을 쓰는 게 좋습니다.

인덱스에 할당해서 어떤 위치든 덮어쓸 수 있고, 항목을 찾는 방법은 두 가지입니다:

js
const names = ["마라", "쿠아메", "유키"];
names[1] = "프리야";
console.log(names.indexOf("유키")); // 2, 없으면 -1
console.log(names.includes("마라")); // true

무언가가 있는지만 궁금할 때는 includes를, 위치까지 알아야 할 때는 indexOf를 사용하세요. 둘 다 ===로 비교하므로, indexOf("2")는 숫자 2를 찾아내지 못합니다.

const로 선언한 배열도 여전히 완전히 바꿀 수 있습니다. const는 이름을 고정할 뿐, 내용물을 고정하지 않습니다. cart를 새로운 배열로 다시 가리키게 할 수는 없지만, 그 안에 담긴 배열에는 얼마든지 push할 수 있습니다.

배열은 변경 가능하며, 핵심 메서드들은 새 배열을 반환하는 게 아니라 원본 배열을 그 자리에서 직접 바꿉니다. push/pop은 끝에서, shift/unshift는 앞에서 동작합니다:

js
const cart = ["사과", "빵"];
cart.push("우유"); // 새 길이를 반환하고, cart를 변경
const removed = cart.pop(); // 제거된 항목을 반환하고, cart를 변경

끝과 앞은 비용이 같지 않습니다. pushpop은 한 자리만 손댑니다. shiftunshift는 남은 모든 요소의 인덱스를 다시 매기므로, 배열 길이에 비례하는 작업량이 들어갑니다. 그래서 큰 배열에 반복적으로 shift를 호출하는 뜨거운 루프는 겉보기보다 훨씬 많은 일을 하고 있는 셈입니다. 순서를 직접 정할 수 있다면 변경 작업을 끝 쪽에 몰아두세요.

인덱스에 할당하면 그 자리를 바로 덮어쓰고, 검색은 필요에 따라 나뉩니다. 존재 여부에는 includes, 위치에는 indexOf(없으면 -1)를 씁니다. 둘 다 엄격한 동등 비교(===)를 사용하므로 타입이 중요합니다:

js
const ids = [1, 2, 3];
console.log(ids.indexOf("2")); // -1, 문자열은 숫자와 일치하지 않음
console.log(ids.includes(2)); // true

const에 관한 이 점은 정확하게 짚어둘 만합니다. 참조 모델이 처음으로 드러나는 지점이기 때문입니다. const는 이름을 하나의 배열에 묶어두고 재할당을 금지할 뿐, 배열의 내용에 대해서는 아무것도 규정하지 않습니다. cart.push(...)는 그 이름이 가리키는 객체를 변경하는 것이고, 이는 cart = [...]와는 전혀 다른 동작입니다. 이 구분이 다음 절에서 다루는 전체 주제입니다.

Juno배열 바꾸기pushpop은 끝에서 추가하고 제거하며, unshiftshift는 앞에서 똑같이 동작합니다. cart[0] = "바나나"처럼 인덱스에 값을 할당해서 항목을 바꿀 수 있고, 무언가를 찾으려면 includesindexOf를 쓰세요. 저를 놀라게 한 부분은, const로 선언한 배열도 여전히 바뀔 수 있다는 점이었습니다. const는 배열 전체를 새 배열로 바꿔치기하는 것만 막을 뿐입니다.
Juno배열 바꾸기 대부분의 수정은 두 쌍으로 처리됩니다. 끝에서는 push/pop, 앞에서는 shift/unshift. 앞쪽 쌍은 나머지 항목을 모두 이동시키므로, 순서를 마음대로 정할 수 있다면 끝을 쓰는 게 낫습니다. includes는 존재 여부를, indexOf는 위치를 알려주며, 둘 다 ===로 비교하므로 "2"는 숫자 2를 찾아내지 못합니다. 그리고 const는 이름만 고정할 뿐 내용물은 고정하지 않으므로, const 배열에도 얼마든지 push할 수 있습니다.
Juno배열 바꾸기 이 메서드들은 배열을 그 자리에서 직접 변경합니다. push/pop은 한 자리만 손대고, shift/unshift는 배열 전체의 인덱스를 다시 매기므로, 큰 배열에 반복적으로 shift를 거는 루프는 그때마다 배열 길이에 비례하는 작업을 하는 셈입니다. includesindexOf 모두 ===를 사용하므로 문자열 인덱스는 숫자와 일치하지 않습니다. 그리고 const는 이름의 재할당만 금지할 뿐, cart.push()로 배열을 변경하는 것은 cart = []와는 전혀 다른 일입니다. 이 간극이 바로 다음에 이어지는 참조 이야기의 핵심입니다.

배열 순회하기

목록이 있으면 보통 그 안의 모든 항목에 대해 어떤 작업을 하고 싶어집니다. 배열을 읽어나가는 가장 깔끔한 방법은 for...of이며, 한 번에 항목 하나씩 건네줍니다:

js
const prices = [4, 9, 2, 7];
for (const price of prices) {
  console.log(price);
}
// 4
// 9
// 2
// 7

인덱스나 카운터를 따로 관리할 필요가 없습니다. for...of는 순서대로 각 값을 건네주고, 이름(price)은 원하는 대로 붙이면 됩니다. 반복문을 이미 배웠다면, 배열을 다룰 때 이게 가장 친숙한 방법입니다.

forEach도 있는데, 이건 각 항목마다 작은 함수를 한 번씩 실행합니다:

js
const names = ["마라", "쿠아메", "유키"];
names.forEach(function (name) {
  console.log("안녕 " + name);
});

둘 다 배열 전체를 순회합니다. 깔끔하게 읽어나가고 싶을 때는 for...of를 쓰고, 배열을 변형하는 법을 배울 때 forEach와 그 친척들을 다시 만나게 됩니다.

배열을 읽을 때 요즘 기본으로 쓰는 방법은 for...of입니다. 각 값을 그대로 건네주므로 인덱스를 관리할 필요도 없고, "하나 차이" 실수가 생길 여지도 없습니다:

js
const prices = [4, 9, 2, 7];
let total = 0;
for (const price of prices) {
  total = total + price;
}
console.log(total); // 22

순서대로 값을 받으면서 깔끔한 코드를 원할 때 for...of를 사용하세요. 인덱스도 함께 필요할 때(예를 들어 목록에 번호를 붙일 때)는 전통적인 카운팅 for 루프나 forEach의 두 번째 매개변수로 인덱스를 얻을 수 있습니다.

forEach는 콜백, 즉 여러분이 건네주는 함수를 항목마다 한 번씩 실행합니다:

js
const names = ["마라", "쿠아메", "유키"];
names.forEach((name) => {
  console.log("안녕 " + name);
});

forEach는 항목마다 로그를 찍는 것 같은 부수 효과를 표현할 때 잘 읽힙니다. 다만 중간에 break로 빠져나올 수는 없으므로, 도중에 멈춰야 할 때는 for...of를 사용하세요. 기존 배열로 새 배열을 만드는 건 별도의 작업이고 배열 메서드에서 그 전용 도구들을 다룹니다.

단순히 읽기만 할 때는 for...of가 관용적인 선택입니다. 값을 직접 순회하고, 인덱스 계산을 피할 수 있으며, breakcontinue를 지원합니다:

js
const prices = [4, 9, 2, 7];
let total = 0;
for (const price of prices) {
  if (price > 8) continue;
  total = total + price;
}
console.log(total); // 13, 9는 건너뜀

forEach는 요소마다 콜백을 받아 처리하며 부수 효과를 표현할 때 깔끔하지만, 이를 표준으로 삼기 전에 알아둘 만한 제약이 두 가지 있습니다. break를 할 수 없어서 항상 끝까지 실행되고, 반환값을 무시하므로 결과를 만들어내려 할 때는 적합한 도구가 아닙니다. 그럴 때는 변형 메서드(map, filter, reduce)가 있고, 이들은 배열 메서드에서 다룹니다.

js
const names = ["마라", "쿠아메", "유키"];
names.forEach((name, index) => {
  console.log(index + ": " + name);
});

콜백의 두 번째 매개변수가 인덱스이며, 이렇게 하면 수동으로 카운터를 두지 않고도 위치를 알아낼 수 있습니다. 대략적인 기준은 이렇습니다. 제어 흐름이 필요하거나 외부 변수에 누적할 때는 for...of, 항목마다의 부수 효과가 더 명확하게 읽힐 때는 forEach, 변경이나 로그가 아니라 새로운 배열을 돌려받고 싶을 때는 변형 메서드입니다.

Juno배열 순회하기for...of는 배열을 순회하는 깔끔한 방법입니다. 각 항목을 순서대로 건네주고, 인덱스를 직접 다룰 일이 없습니다. forEach는 항목마다 작은 함수를 한 번씩 실행하는데, 이것도 유용합니다. 둘 다 목록 전체를 훑으므로, 처음부터 끝까지 읽어나가고 싶다면 for...of를 고르세요. 배열을 변형하는 법을 배우면 더 다양한 도구를 만나게 됩니다.
Juno배열 순회하기for...of는 배열을 읽을 때 기본으로 쓰는 방법입니다. 순서대로 값을 얻고, 인덱스를 관리할 필요도 없으며, 도중에 멈춰야 할 때는 break가 잘 동작합니다. forEach는 항목마다 콜백을 실행해서 로그 같은 부수 효과를 표현할 때 잘 읽히지만, break를 할 수 없어서 항상 끝까지 실행됩니다. 기존 배열로 새 배열을 만드는 건 자기만의 메서드가 있는 별도의 작업입니다. 헷갈릴 때는 for...of를 쓰세요.
Juno배열 순회하기for...of는 값을 직접 순회하고 breakcontinue를 지원하므로, 제어 흐름이 필요하거나 외부 변수에 누적할 때는 이 방법이 낫습니다. forEach는 항목마다의 부수 효과를 표현할 때 깔끔하게 읽히지만 break를 할 수 없고 반환값을 무시하므로, 결과를 만들어내야 할 때는 적합한 도구가 아닙니다. 새로운 배열을 돌려받고 싶다면 반복문 대신 변형 메서드를 사용하세요. 콜백의 두 번째 매개변수는 위치가 필요할 때 인덱스를 알려줍니다.

배열은 참조로 전달됩니다

미리 알아두면 놀라지 않을 동작이 하나 있습니다. 배열 변수를 다른 이름에 복사해도 배열이 하나 더 생기는 게 아닙니다. 두 이름 모두 같은 배열을 가리킵니다.

js
const original = [1, 2, 3];
const copy = original;
copy.push(4);
console.log(original); // [1, 2, 3, 4]

copy에 push했는데 original이 바뀌었습니다. 배열이 원래부터 하나뿐이었기 때문입니다. =는 두 번째 이름에게 새로 복사된 목록을 준 게 아니라, 같은 목록을 그대로 준 것입니다. 사람들이 배열이 참조로 전달된다고 말할 때 뜻하는 게 바로 이겁니다. 변수는 목록 자체가 아니라 목록을 가리키는 포인터를 담고 있습니다.

진짜로 독립된 복사본을 만들려면, ...로 배열을 새 배열에 펼쳐 넣으세요:

js
const original = [1, 2, 3];
const copy = [...original];
copy.push(4);
console.log(original); // [1, 2, 3], 그대로 유지됨

숫자나 문자열은 값으로 전달됩니다. 변수를 복사하면 값 자체가 복사됩니다. 배열은 다릅니다. 참조로 전달되므로, 변수를 복사하면 포인터가 복사되고, 두 이름 모두 같은 배열을 가리키게 됩니다.

js
const original = [1, 2, 3];
const shared = original;
shared.push(4);
console.log(original); // [1, 2, 3, 4], 같은 배열

이건 앞에서 다룬 const 이야기와 같은 원리입니다. 배열은 객체이고, 변수는 그 객체 자체가 아니라 그 객체에 대한 참조를 담고 있습니다. 어느 쪽 이름을 통해서든 변경하면, 두 이름이 공유하는 그 하나의 배열이 바뀝니다.

독립된 복사본이 필요할 때는 새 배열에 펼쳐 넣으세요. ...는 각 항목을 그대로 복사해 넣습니다:

js
const original = [1, 2, 3];
const copy = [...original];
copy.push(4);
console.log(original); // [1, 2, 3], 별개의 배열

이건 얕은 복사입니다. 새 배열은 독립된 목록이지만, 항목 자체가 배열이었다면 두 복사본은 그 안쪽 배열들을 여전히 공유합니다. 숫자와 문자열 같은 단순한 값만 다룰 때는 얕은 복사로 충분합니다.

원시값(숫자, 문자열, 불리언)은 값으로 전달되고, 배열은 객체이므로 참조로 전달됩니다. 배열을 "담고 있는" 변수는 실제로는 그 배열에 대한 참조를 담고 있을 뿐이므로, 할당은 참조를 복사하는 것이고, 그 배열을 가리키는 모든 이름은 모든 변경을 그대로 보게 됩니다:

js
const original = [1, 2, 3];
const alias = original;
alias.push(4);
console.log(original); // [1, 2, 3, 4]
console.log(original === alias); // true, 같은 배열

이래서 const와 불변성은 별개의 문제입니다. const는 참조를 고정하고, 변경은 그 참조가 가리키는 대상을 바꿉니다. 이것은 또한 불변성을 선호하는 근거이기도 합니다. 즉 배열을 그 자리에서 바꾸는 대신 새 배열을 만들어내는 방식입니다. 공유되는 가변 상태는, 어떤 함수가 전달받은 배열을 변경하면 그 참조를 가지고 있는 다른 모든 곳에서도 조용히 바뀌어버린다는 뜻이고, 이건 추적하기 어려운 종류의 버그입니다. 새 배열을 반환하면 각 호출자의 데이터를 각자의 것으로 유지할 수 있습니다.

전개(spread) 연산자는 얕은 복사를 만듭니다. 같은 항목들을 복사해 담은 새로운 바깥 배열이 생기는 것입니다.

js
const original = [1, 2, 3];
const copy = [...original];
console.log(copy === original); // false, 서로 다른 배열

여기서 중요한 단어는 "얕은"입니다. 새 배열은 독립적이지만, 그 안에 있는 중첩 배열들은 여전히 참조로 공유되므로, 깊은 구조에는 전개만으로는 부족합니다. 지금까지 다룬 것처럼 원시값만 담긴 배열이라면, 전개 하나로 완전한 복사가 됩니다.

구조를 선택하는 문제로 돌아가보면, 순서가 있는 비슷한 것들의 목록이 있고 위치나 개수가 중요할 때, 이를테면 가격들의 대기열이나 이름들의 나열 같은 경우에는 배열이 알맞은 도구입니다. 반대로 위치가 아니라 의미 있는 키로 값을 찾아보고 싶을 때는 객체가 그 역할을 하고, 이런 배열 작업의 상당 부분은 결국 함수 안에 자리 잡게 됩니다.

Juno배열은 참조로 전달됩니다=로 배열 변수를 복사해도 배열이 하나 더 생기지 않습니다. 두 이름 모두 같은 배열을 가리키므로, 어느 쪽을 통해 바꿔도 양쪽 모두에서 보입니다. 저도 이것 때문에 여러 번 당했습니다. 진짜로 독립된 복사본이 필요할 때는 [...original]로 펼쳐서 따로 바꿀 수 있는 새 배열을 만드세요.
Juno배열은 참조로 전달됩니다 숫자와 문자열은 값으로 복사되지만, 배열은 참조로 복사됩니다. 그래서 const b = a는 하나의 배열에 대한 이름 두 개를 만드는 것이고, 어느 쪽을 통해 변경해도 둘 다에 영향을 줍니다. 이게 const로 선언한 배열도 여전히 변경 가능한 것과 같은 이유입니다. 독립된 복사본이 필요할 때는 [...original]을 쓰되, 이게 얕은 복사라는 점을 기억하세요. 숫자와 문자열로 이루어진 배열에는 이 정도면 딱 맞습니다.
Juno배열은 참조로 전달됩니다 배열은 참조로 전달되는 객체이므로, 할당은 포인터를 복사하고 모든 이름이 모든 변경을 보게 됩니다. 이 때문에 const(참조를 고정)와 불변성(대상을 바꿈)이 분리되고, 전달받은 배열을 변경하는 함수는 그 참조를 가진 모든 곳에서 바뀌어버리므로 그 자리에서 바꾸는 대신 새 배열을 선호할 이유가 됩니다. 전개는 얕은 복사를 만듭니다. 최상위 수준에서는 독립적이지만 중첩된 배열은 공유됩니다. 순서와 개수가 중요할 때는 배열을, 키로 값을 찾아보고 싶을 때는 객체를 선택하세요.

배열, 그 다음은

배열은 하나의 이름 아래 순서 있는 목록을 담아줍니다. []로 만들고, 0부터 시작하는 인덱스로 읽고, pushpop으로 바꾸고, for...of로 순회합니다. 이 장을 넘어서도 꼭 기억해둘 한 가지는, 배열이 참조로 전달되기 때문에 변수를 복사하면 목록이 복제되는 게 아니라 공유된다는 점입니다.

자연스러운 다음 단계는 하나의 배열로 다른 배열을 만드는 것, 즉 목록을 걸러내거나 모든 항목을 변형하거나 전부 더하는 작업을 반복문을 직접 짜지 않고 처리하는 방법입니다. 그게 배열 메서드입니다. 위치가 아니라 이름으로 값을 찾아봐야 할 때는 객체가 그 구조를 제공합니다.