인덱스 컬렉션

인덱스 컬렉션 (Indexed collections)

이 장에서는 인덱스 값(index value)에 의해 순서가 정해진 데이터 컬렉션을 소개합니다. 여기에는 Array 객체와 TypedArray 객체 같은 배열 및 배열형(array-like) 구조가 포함됩니다.

배열(array)은 이름과 인덱스로 참조하는 값들의 순서 있는 목록입니다. 예를 들어 직원 번호로 인덱싱된 직원 이름을 담는 emp라는 배열을 생각해 봅시다. 그러면 emp[0]은 직원 번호 0, emp[1]은 직원 번호 1, 이런 식이 됩니다.

JavaScript에는 명시적인 배열 데이터 타입이 없습니다. 그러나 미리 정의된 Array 객체와 그 메서드를 사용해 애플리케이션에서 배열을 다룰 수 있습니다. Array 객체에는 조인, 뒤집기, 정렬 등 배열을 다양하게 조작하는 메서드가 있습니다. 또한 배열 길이를 결정하는 속성과 정규 표현식과 함께 사용할 다른 속성들도 있습니다.

이 글에서는 배열에 초점을 맞추지만, 배열과 타입 배열(typed array)은 많은 유사한 메서드를 공유하므로 동일한 개념 중 상당수가 타입 배열에도 적용됩니다. 타입 배열에 대한 자세한 내용은 타입 배열 가이드를 참고하세요.

출처: Indexed collections

본문

배열 생성

다음 문장들은 동일한 배열을 만듭니다.

const arr1 = new Array(element0, element1, /* …, */ elementN);
const arr2 = Array(element0, element1, /* …, */ elementN);
const arr3 = [element0, element1, /* …, */ elementN];

여기서 element0, element1, …, elementN은 배열 요소의 값 목록입니다. 이 값들이 지정되면 배열이 이 값들로 초기화되고, 배열의 length 속성은 인자 개수로 설정됩니다.

대괄호 문법을 "배열 리터럴(array literal)" 또는 "배열 초기화자(array initializer)"라고 합니다. 배열 생성의 다른 형태보다 짧으므로 일반적으로 선호됩니다. 자세한 내용은 배열 리터럴을 참고하세요.

0이 아닌 길이지만 항목이 없는 배열을 만들려면 다음 중 하나를 사용할 수 있습니다.

// This...
const arr1 = new Array(arrayLength);

// … results in the same array as this
const arr2 = Array(arrayLength);

// This has exactly the same effect
const arr3 = [];
arr3.length = arrayLength;

참고: 위 코드에서 arrayLengthNumber여야 합니다. 그렇지 않으면 단일 요소(제공된 값)를 가진 배열이 생성됩니다. arr.length를 호출하면 arrayLength를 반환하지만, 배열에는 실제 요소가 없습니다. for...in 루프는 배열에서 어떤 속성도 찾지 못할 것입니다.

위처럼 새로 정의한 변수 외에도, 배열을 새 객체나 기존 객체의 속성으로 할당할 수 있습니다.

const obj = {};
// …
obj.prop = [element0, element1, /* …, */ elementN];

// OR
const obj = { prop: [element0, element1, /* …, */ elementN] };

단일 요소로 배열을 초기화하려고 하는데 그 요소가 Number라면 반드시 대괄호 문법을 사용해야 합니다. 단일 Number 값이 Array() 생성자나 함수에 전달되면 단일 요소가 아니라 arrayLength로 해석되기 때문입니다.

다음은 단일 요소(숫자 42)만 가진 배열을 만듭니다.

const arr = [42];

다음은 요소가 없고 arr.length가 42인 배열을 만듭니다.

const arr = Array(42);

이는 다음과 동일합니다.

const arr = [];
arr.length = 42;

N이 소수 부분이 0이 아닌 정수가 아닌 수일 때 Array(N)을 호출하면 RangeError가 발생합니다. 다음 예제가 이 동작을 보여줍니다.

const arr = Array(9.3); // RangeError: Invalid array length

코드가 임의의 데이터 타입의 단일 요소를 가진 배열을 만들어야 한다면 배열 리터럴을 사용하는 것이 더 안전합니다. 또는 먼저 빈 배열을 만든 다음 단일 요소를 추가하세요.

단일 요소로 배열을 만들려면 Array.of 정적 메서드를 사용할 수도 있습니다.

const arr = Array.of(9.3); // arr contains only one element 9.3

배열 요소 참조

요소도 속성이므로, 속성 접근자(property accessor)를 사용해 접근할 수 있습니다. 다음과 같은 배열을 정의했다고 가정해 봅시다.

const myArray = ["Wind", "Rain", "Fire"];

배열의 첫 번째 요소는 myArray[0], 두 번째 요소는 myArray[1] 등으로 참조할 수 있습니다. 요소의 인덱스는 0부터 시작합니다.

참고: 속성 접근자를 사용해 객체처럼 배열의 다른 속성들에도 접근할 수 있습니다.

const arr = ["one", "two", "three"];
arr[2]; // three
arr["length"]; // 3

배열 채우기

요소에 값을 할당해 배열을 채울 수 있습니다. 예:

const emp = [];
emp[0] = "Casey Jones";
emp[1] = "Phil Lesh";
emp[2] = "August West";

참고: 위 코드의 배열 연산자에 정수가 아닌 값을 제공하면 배열 요소가 아니라 배열을 나타내는 객체에 속성이 생성됩니다.

const arr = [];
arr[3.4] = "Oranges";
console.log(arr.length); // 0
console.log(Object.hasOwn(arr, 3.4)); // true

배열을 만들 때 채울 수도 있습니다.

const myArray = new Array("Hello", myVar, 3.14159);
// OR
const myArray = ["Mango", "Apple", "Orange"];

length 이해하기

구현 수준에서 JavaScript의 배열은 실제로 요소를 표준 객체 속성으로 저장하며, 배열 인덱스를 속성 이름으로 사용합니다.

length 속성은 특별합니다. 그 값은 항상 마지막 요소의 인덱스보다 큰 양의 정수입니다(존재하는 경우). (아래 예제에서 'Dusty'는 인덱스 30에 있으므로 cats.length는 30 + 1 = 31을 반환합니다.)

기억하세요. JavaScript 배열 인덱스는 0부터 시작합니다. 즉 0에서 시작하지 1에서 시작하지 않습니다. 이는 length 속성이 배열에 저장된 가장 높은 인덱스보다 1 더 크다는 뜻입니다.

const cats = [];
cats[30] = ["Dusty"];
console.log(cats.length); // 31

length 속성에 값을 할당할 수도 있습니다. 저장된 항목 수보다 짧은 값을 쓰면 배열이 잘립니다(truncate). 0을 쓰면 배열이 완전히 비워집니다.

const cats = ["Dusty", "Misty", "Twiggy"];
console.log(cats.length); // 3

cats.length = 2;
console.log(cats); // [ 'Dusty', 'Misty' ] - Twiggy has been removed

cats.length = 0;
console.log(cats); // []; the cats array is empty

cats.length = 3;
console.log(cats); // [ <3 empty items> ]

배열 반복

흔한 연산은 배열의 값을 반복하면서 각각을 어떤 방식으로 처리하는 것입니다.

const colors = ["red", "green", "blue"];
for (let i = 0; i < colors.length; i++) {
 console.log(colors[i]);
}

배열의 어떤 요소도 불리언 문맥에서 false로 평가되지 않는다는 것을 알고 있다면 — 예를 들어 배열이 DOM 노드만으로 구성된 경우 — 더 효율적인 관용구를 사용할 수 있습니다.

const divs = document.getElementsByTagName("div");
for (let i = 0, div; (div = divs[i]); i++) {
 /* Process div in some way */
}

이렇게 하면 배열 길이를 확인하는 오버헤드를 피하고, 매 루프마다 div 변수가 현재 항목으로 다시 할당되어 편리합니다.

forEach() 메서드는 배열을 반복하는 또 다른 방법을 제공합니다.

const colors = ["red", "green", "blue"];
colors.forEach((color) => console.log(color));
// red
// green
// blue

forEach에 전달된 함수는 배열의 각 항목마다 한 번씩 실행되며, 배열 항목이 함수의 인자로 전달됩니다. 할당되지 않은 값은 forEach 루프에서 반복되지 않습니다.

배열 정의 시 생략된 요소는 forEach로 반복할 때 나열되지 않지만, 요소에 undefined를 수동으로 할당한 경우에는 나열됩니다.

const sparseArray = ["first", "second", , "fourth"];

sparseArray.forEach((element) => {
 console.log(element);
});
// Logs:
// first
// second
// fourth

if (sparseArray[2] === undefined) {
 console.log("sparseArray[2] is undefined"); // true
}

const nonsparseArray = ["first", "second", undefined, "fourth"];

nonsparseArray.forEach((element) => {
 console.log(element);
});
// Logs:
// first
// second
// undefined
// fourth

JavaScript 배열 요소는 표준 객체 속성으로 저장되므로, for...in 루프로 배열을 반복하는 것은 권장하지 않습니다. 일반 요소와 모든 열거 가능한 속성이 나열되기 때문입니다.

배열 메서드

Array 객체에는 다음 메서드가 있습니다.

concat() 메서드는 둘 이상의 배열을 결합해 새 배열을 반환합니다.

let myArray = ["1", "2", "3"];
myArray = myArray.concat("a", "b", "c");
// myArray is now ["1", "2", "3", "a", "b", "c"]

join() 메서드는 배열의 모든 요소를 문자열로 결합합니다.

const myArray = ["Wind", "Rain", "Fire"];
const list = myArray.join(" - "); // list is "Wind - Rain - Fire"

push() 메서드는 배열 끝에 하나 이상의 요소를 추가하고 배열의 결과 길이를 반환합니다.

const myArray = ["1", "2"];
myArray.push("3"); // myArray is now ["1", "2", "3"]

pop() 메서드는 배열에서 마지막 요소를 제거하고 그 요소를 반환합니다.

const myArray = ["1", "2", "3"];
const last = myArray.pop();
// myArray is now ["1", "2"], last = "3"

shift() 메서드는 배열에서 첫 번째 요소를 제거하고 그 요소를 반환합니다.

const myArray = ["1", "2", "3"];
const first = myArray.shift();
// myArray is now ["2", "3"], first is "1"

unshift() 메서드는 배열 앞에 하나 이상의 요소를 추가하고 배열의 새 길이를 반환합니다.

const myArray = ["1", "2", "3"];
myArray.unshift("4", "5");
// myArray becomes ["4", "5", "1", "2", "3"]

slice() 메서드는 배열의 한 구간을 추출해 새 배열을 반환합니다.

let myArray = ["a", "b", "c", "d", "e"];
myArray = myArray.slice(1, 4); // [ "b", "c", "d"]
// starts at index 1 and extracts all elements
// until index 3

at() 메서드는 배열에서 지정된 인덱스의 요소를 반환하며, 인덱스가 범위를 벗어나면 undefined를 반환합니다. 특히 배열 끝에서 요소에 접근하는 음수 인덱스에 사용됩니다.

const myArray = ["a", "b", "c", "d", "e"];
myArray.at(-2); // "d", the second-last element of myArray

splice() 메서드는 배열에서 요소를 제거하고 (선택적으로) 교체합니다. 배열에서 제거된 항목을 반환합니다.

const myArray = ["1", "2", "3", "4", "5"];
myArray.splice(1, 3, "a", "b", "c", "d");
// myArray is now ["1", "a", "b", "c", "d", "5"]
// This code started at index one (or where the "2" was),
// removed 3 elements there, and then inserted all consecutive
// elements in its place.

reverse() 메서드는 배열의 요소를 제자리에서(in place) 뒤집습니다. 첫 번째 배열 요소가 마지막이 되고 마지막이 첫 번째가 됩니다. 배열에 대한 참조를 반환합니다.

const myArray = ["1", "2", "3"];
myArray.reverse();
// transposes the array so that myArray = ["3", "2", "1"]

flat() 메서드는 모든 하위 배열 요소를 지정된 깊이까지 재귀적으로 결합한 새 배열을 반환합니다.

let myArray = [1, 2, [3, 4]];
myArray = myArray.flat();
// myArray is now [1, 2, 3, 4], since the [3, 4] subarray is flattened

sort() 메서드는 배열의 요소를 제자리에서 정렬하고 배열에 대한 참조를 반환합니다.

const myArray = ["Wind", "Rain", "Fire"];
myArray.sort();
// sorts the array so that myArray = ["Fire", "Rain", "Wind"]

sort()는 배열 요소를 어떻게 비교할지 결정하는 콜백 함수를 받을 수도 있습니다. 콜백 함수는 배열의 두 값을 인자로 받아 호출됩니다. 함수는 이 두 값을 비교하고 순서를 나타내는 양수, 음수, 또는 0을 반환합니다. 예를 들어 다음은 문자열의 마지막 글자 기준으로 배열을 정렬합니다.

const sortFn = (a, b) => {
 if (a[a.length - 1] < b[b.length - 1]) {
   return -1; // Negative number => a < b, a comes before b
 } else if (a[a.length - 1] > b[b.length - 1]) {
   return 1; // Positive number => a > b, a comes after b
 }
 return 0; // Zero => a = b, a and b keep their original order
};
myArray.sort(sortFn);
// sorts the array so that myArray = ["Wind","Fire","Rain"]
  • 정렬 시스템에서 ab보다 작으면 -1(또는 음수)을 반환합니다.
  • 정렬 시스템에서 ab보다 크면 1(또는 양수)을 반환합니다.
  • ab가 동등하다고 간주되면 0을 반환합니다.

indexOf() 메서드는 배열에서 searchElement를 검색하고 첫 번째 일치의 인덱스를 반환합니다.

const a = ["a", "b", "a", "b", "a"];
console.log(a.indexOf("b")); // 1

// Now try again, starting from after the last match
console.log(a.indexOf("b", 2)); // 3
console.log(a.indexOf("z")); // -1, because 'z' was not found

lastIndexOf() 메서드는 indexOf처럼 동작하지만, 끝에서 시작해 역방향으로 검색합니다.

const a = ["a", "b", "c", "d", "a", "b"];
console.log(a.lastIndexOf("b")); // 5

// Now try again, starting from before the last match
console.log(a.lastIndexOf("b", 4)); // 1
console.log(a.lastIndexOf("z")); // -1

forEach() 메서드는 모든 배열 항목에 대해 callback을 실행하고 undefined를 반환합니다.

const a = ["a", "b", "c"];
a.forEach((element) => {
 console.log(element);
});
// Logs:
// a
// b
// c

콜백을 받는 forEach (및 아래 다른) 메서드를 반복 메서드(iterative method)라고 합니다. 어떤 방식으로든 전체 배열을 반복하기 때문입니다. 각각은 thisArg라는 선택적 두 번째 인자를 받습니다. 제공되면 thisArg가 콜백 함수 본문 안에서 this 키워드의 값이 됩니다. 제공되지 않으면, 함수가 명시적 객체 문맥 밖에서 호출되는 다른 경우처럼, 함수가 엄격(strict)하지 않을 때 this는 전역 객체(window, globalThis 등)를 가리키고, 함수가 엄격할 때는 undefined를 가리킵니다.

참고: 앞서 소개한 sort() 메서드는 반복 메서드가 아닙니다. 그 콜백 함수는 비교에만 사용되며 요소 순서에 따른 특정 순서로 호출되지 않을 수 있기 때문입니다. sort()thisArg 매개변수도 받지 않습니다.

map() 메서드는 모든 배열 항목에 대해 callback을 실행한 반환값으로 구성된 새 배열을 반환합니다.

const a1 = ["a", "b", "c"];
const a2 = a1.map((item) => item.toUpperCase());
console.log(a2); // ['A', 'B', 'C']

flatMap() 메서드는 map()을 실행한 다음 깊이 1의 flat()을 실행합니다.

const a1 = ["a", "b", "c"];
const a2 = a1.flatMap((item) => [item.toUpperCase(), item.toLowerCase()]);
console.log(a2); // ['A', 'a', 'B', 'b', 'C', 'c']

filter() 메서드는 callbacktrue를 반환한 항목들을 담은 새 배열을 반환합니다.

const a1 = ["a", 10, "b", 20, "c", 30];
const a2 = a1.filter((item) => typeof item === "number");
console.log(a2); // [10, 20, 30]

find() 메서드는 callbacktrue를 반환한 첫 번째 항목을 반환합니다.

const a1 = ["a", 10, "b", 20, "c", 30];
const i = a1.find((item) => typeof item === "number");
console.log(i); // 10

findLast() 메서드는 callbacktrue를 반환한 마지막 항목을 반환합니다.

const a1 = ["a", 10, "b", 20, "c", 30];
const i = a1.findLast((item) => typeof item === "number");
console.log(i); // 30

findIndex() 메서드는 callbacktrue를 반환한 첫 번째 항목의 인덱스를 반환합니다.

const a1 = ["a", 10, "b", 20, "c", 30];
const i = a1.findIndex((item) => typeof item === "number");
console.log(i); // 1

findLastIndex() 메서드는 callbacktrue를 반환한 마지막 항목의 인덱스를 반환합니다.

const a1 = ["a", 10, "b", 20, "c", 30];
const i = a1.findLastIndex((item) => typeof item === "number");
console.log(i); // 5

every() 메서드는 배열의 모든 항목에 대해 callbacktrue를 반환하면 true를 반환합니다.

function isNumber(value) {
 return typeof value === "number";
}
const a1 = [1, 2, 3];
console.log(a1.every(isNumber)); // true
const a2 = [1, "2", 3];
console.log(a2.every(isNumber)); // false

some() 메서드는 배열의 적어도 하나의 항목에 대해 callbacktrue를 반환하면 true를 반환합니다.

function isNumber(value) {
 return typeof value === "number";
}
const a1 = [1, 2, 3];
console.log(a1.some(isNumber)); // true
const a2 = [1, "2", 3];
console.log(a2.some(isNumber)); // true
const a3 = ["1", "2", "3"];
console.log(a3.some(isNumber)); // false

reduce() 메서드는 항목 목록을 단일 값으로 축소하기 위해 배열의 각 값에 대해 callback(accumulator, currentValue, currentIndex, array)을 적용합니다. reduce 함수는 콜백 함수가 반환한 최종 값을 반환합니다.

initialValue가 지정되면, callback이 첫 번째 매개변수 값으로 initialValue, 두 번째 매개변수 값으로 배열의 첫 번째 항목 값을 받아 호출됩니다.

initialValue가 지정되지 않으면, callback의 첫 두 매개변수 값은 배열의 첫 번째와 두 번째 요소가 됩니다. 이후의 모든 호출에서 첫 번째 매개변수 값은 이전 호출에서 callback이 반환한 값이 되고, 두 번째 매개변수 값은 배열의 다음 값이 됩니다.

callback이 처리 중인 항목의 인덱스나 전체 배열에 접근해야 한다면 선택적 매개변수로 사용할 수 있습니다.

const a = [10, 20, 30];
const total = a.reduce(
 (accumulator, currentValue) => accumulator + currentValue,
 0,
);
console.log(total); // 60

reduceRight() 메서드는 reduce()처럼 동작하지만 마지막 요소에서 시작합니다.

reducereduceRight는 반복 배열 메서드 중 가장 덜 직관적입니다. 시퀀스를 단일 값으로 줄이기 위해 두 값을 재귀적으로 결합하는 알고리즘에 사용해야 합니다.

배열 변환

배열과 다른 데이터 구조 사이에서 앞뒤로 변환할 수 있습니다.

배열 요소 그룹화

Object.groupBy() 메서드는 현재 요소의 그룹을 나타내는 문자열을 반환하는 테스트 함수를 사용해 배열의 요소를 그룹화하는 데 사용할 수 있습니다.

여기 nametype을 가진 "food" 객체를 담은 재고 배열이 있습니다.

const inventory = [
 { name: "asparagus", type: "vegetables" },
 { name: "bananas", type: "fruit" },
 { name: "goat", type: "meat" },
 { name: "cherries", type: "fruit" },
 { name: "fish", type: "meat" },
];

Object.groupBy()를 사용하려면 현재 요소, 선택적으로 현재 인덱스와 배열로 호출되고 요소의 그룹을 나타내는 문자열을 반환하는 콜백 함수를 제공합니다.

아래 코드는 화살표 함수를 사용해 각 배열 요소의 type을 반환합니다(전달된 객체에서 type 요소를 풀어내기 위해 함수 인자에 객체 구조 분해 문법을 사용합니다). 결과는 콜백이 반환한 고유 문자열로 이름 붙은 속성을 갖는 객체입니다. 각 속성에는 그룹의 요소를 담은 배열이 할당됩니다.

const result = Object.groupBy(inventory, ({ type }) => type);
console.log(result);
// Logs
// {
//   vegetables: [{ name: 'asparagus', type: 'vegetables' }],
//   fruit: [
//     { name: 'bananas', type: 'fruit' },
//     { name: 'cherries', type: 'fruit' }
//   ],
//   meat: [
//     { name: 'goat', type: 'meat' },
//     { name: 'fish', type: 'meat' }
//   ]
// }

반환된 객체가 원래 배열과 동일한 요소를 참조한다는 점에 주의하세요(깊은 복사가 아님). 이 요소들의 내부 구조를 변경하면 원래 배열과 반환된 객체 양쪽에 반영됩니다.

문자열을 키로 사용할 수 없을 때 — 예를 들어 그룹화할 정보가 변경될 수 있는 객체와 연결된 경우 — 대신 Map.groupBy()를 사용할 수 있습니다. 이는 Object.groupBy()와 매우 유사하지만, 배열의 요소를 임의의 값(객체 또는 원시 값)을 키로 쓸 수 있는 Map으로 그룹화합니다.

희소 배열 (Sparse arrays)

배열은 "빈 슬롯(empty slots)"을 포함할 수 있는데, 이는 undefined 값으로 채워진 슬롯과 다릅니다. 빈 슬롯은 다음 중 한 가지 방법으로 만들 수 있습니다.

// Array constructor:
const a = Array(5); // [ <5 empty items> ]

// Consecutive commas in array literal:
const b = [1, 2, , , 5]; // [ 1, 2, <2 empty items>, 5 ]

// Directly setting a slot with index greater than array.length:
const c = [1, 2];
c[4] = 5; // [ 1, 2, <2 empty items>, 5 ]

// Elongating an array by directly setting .length:
const d = [1, 2];
d.length = 5; // [ 1, 2, <3 empty items> ]

// Deleting an element:
const e = [1, 2, 3, 4, 5];
delete e[2]; // [ 1, 2, <1 empty item>, 4, 5 ]

일부 연산에서 빈 슬롯은 undefined로 채워진 것처럼 동작합니다.

const arr = [1, 2, , , 5]; // Create a sparse array

// Indexed access
console.log(arr[2]); // undefined

// For...of
for (const i of arr) {
 console.log(i);
}
// Logs: 1 2 undefined undefined 5

// Spreading
const another = [...arr]; // "another" is [ 1, 2, undefined, undefined, 5 ]

하지만 다른 연산(특히 배열 반복 메서드)에서는 빈 슬롯이 건너뛰어집니다.

const mapped = arr.map((i) => i + 1); // [ 2, 3, <2 empty items>, 6 ]
arr.forEach((i) => console.log(i)); // 1 2 5
const filtered = arr.filter(() => true); // [ 1, 2, 5 ]
const hasFalsy = arr.some((k) => !k); // false

// Property enumeration
const keys = Object.keys(arr); // [ '0', '1', '4' ]
for (const key in arr) {
 console.log(key);
}
// Logs: '0' '1' '4'
// Spreading into an object uses property enumeration, not the array's iterator
const objectSpread = { ...arr }; // { '0': 1, '1': 2, '4': 5 }

배열 메서드가 희소 배열과 어떻게 동작하는지에 대한 전체 목록은 Array 참조 페이지를 참고하세요.

다차원 배열

배열은 중첩될 수 있습니다. 즉 배열이 다른 배열을 요소로 포함할 수 있습니다. JavaScript 배열의 이 특성을 사용해 다차원 배열을 만들 수 있습니다.

다음 코드는 2차원 배열을 만듭니다.

const a = new Array(4);
for (let i = 0; i < 4; i++) {
 a[i] = new Array(4);
 for (let j = 0; j < 4; j++) {
   a[i][j] = `[${i}, ${j}]`;
 }
}

이 예제는 다음 행을 가진 배열을 만듭니다.

Row 0: [0, 0] [0, 1] [0, 2] [0, 3]
Row 1: [1, 0] [1, 1] [1, 2] [1, 3]
Row 2: [2, 0] [2, 1] [2, 2] [2, 3]
Row 3: [3, 0] [3, 1] [3, 2] [3, 3]

배열을 사용한 다른 속성 저장

배열은 객체처럼 관련 정보를 저장하는 데 사용될 수도 있습니다.

const arr = [1, 2, 3];
arr.property = "value";
console.log(arr.property); // "value"

예를 들어, 배열이 정규 표현식과 문자열의 일치 결과일 때, 배열은 일치에 대한 정보를 제공하는 속성과 요소를 반환합니다. 배열은 RegExp.prototype.exec(), String.prototype.match(), String.prototype.split()의 반환값입니다. 정규 표현식과 함께 배열을 사용하는 방법은 정규 표현식을 참고하세요.

배열형 객체 다루기

document.getElementsByTagName()이 반환하는 NodeList나 함수 본문 안에서 사용 가능한 arguments 객체 같은 일부 JavaScript 객체는 표면상 배열처럼 보이고 동작하지만 모든 배열 메서드를 공유하지는 않습니다. arguments 객체는 length 속성을 제공하지만 forEach() 같은 배열 메서드는 구현하지 않습니다.

배열 메서드는 배열형 객체에 직접 호출할 수 없습니다.

function printArguments() {
 arguments.forEach((item) => {
   console.log(item);
 }); // TypeError: arguments.forEach is not a function
}

하지만 Function.prototype.call()을 사용해 간접적으로 호출할 수 있습니다.

function printArguments() {
 Array.prototype.forEach.call(arguments, (item) => {
   console.log(item);
 });
}

문자열도 배열과 유사하게 문자에 순차적으로 접근할 수 있으므로, 배열 프로토타입 메서드를 문자열에도 사용할 수 있습니다.

Array.prototype.forEach.call("a string", (chr) => {
 console.log(chr);
});

더 알아보기