Array
Baseline
Widely available
*
This feature is well established and works across many devices and browser versions. It’s been available across browsers since 2015년 7월.
* Some parts of this feature may have varying levels of support.
다른 프로그래밍 언어의 배열과 마찬가지로, Array 객체는 여러 항목의 컬렉션을 단일 변수 이름 아래 저장할 수 있고, 일반적인 배열 연산을 수행하기 위한 멤버가 있습니다.
설명
JavaScript에서 배열은 원시 값이 아니라 다음과 같은 핵심적인 특성을 가진 Array 객체입니다.
- JavaScript 배열은 크기를 조정이 가능하고, 다양한 데이터 형식을 혼합하여 저장할 수 있습니다. (이러한 특성이 바람직하지 않은 경우라면, 형식화 배열을 대신 사용하세요.)
- JavaScript 배열은 연관 배열이 아니므로 임의의 문자열을 인덱스로 사용하여 배열 요소에 접근할 수 없습니다. 하지만, 음수가 아닌 정수(또는 해당 수의 문자열 형식)를 인덱스로 사용하여 접근해야 합니다.
- JavaScript 배열은 0 인덱스입니다. 배열의 첫 번째 요소는 인덱스
0, 두 번째 요소는 인덱스1, 마지막 요소는 배열의length속성 값에서 1을 뺀 값에 위치합니다. - JavaScript 배열 복사 연산은 얕은 복사본을 생성합니다. (모든 JavaScript 객체의 모든 표준 내장 복사 연산은 깊은 복사본이 아닌 얕은 복사본을 생성합니다).
배열 인덱스
Array 객체는 (연관 배열에서처럼) 임의의 문자열을 요소 인덱스로 사용할 수 없으며 음수가 아닌 정수(또는 해당 수의 문자열 형식)를 사용해야 합니다. 정수가 아닌 것을 통해 배열의 요소를 설정하거나 접근하려고 하면, 배열 목록 자체에서 요소를 설정하거나 검색하는 것이 아니라 해당 배열의 객체 속성 컬렉션과 연결된 변수를 설정하거나 접근하게 됩니다. 배열의 객체 속성과 배열의 요소 목록은 별개이며, 배열의 순회 및 수정 연산은 이렇게 이름 붙여진 속성에 적용할 수 없습니다.
배열 요소는 toString이 속성인 것과 같은 방식으로 객체 속성입니다(하지만, 정확히 말하자면 toString()은 메서드입니다). 그럼에도 불구하고 다음과 같이 배열의 요소에 접근하려고 하면 속성 이름이 유효하지 않기 때문에 구문 오류가 발생합니다.
arr.0; // 구문 오류
JavaScript 구문에서 숫자로 시작하는 속성은 점 표기법 대신 대괄호 표기법을 사용하여 접근해야 합니다. 배열 인덱스를 따옴표로 묶을 수도 있지만 (예: years[2] 대신 years['2']), 일반적으로는 필요하지 않습니다.
years[2]의 2는 JavaScript 엔진에 의해 암시적 toString 변환을 통해 문자열로 강제 변환됩니다. 결과적으로 '2'와 '02'는 years 객체에서 서로 다른 두 개의 슬롯을 참조하게 되며, 다음 예제는 true 일 수 있습니다.
console.log(years["2"] !== years["02"]);
years['2']만이 실제 배열 인덱스입니다. years['02']는 배열 순회에서 방문되지 않는 임의의 문자열 속성입니다.
length와 숫자 속성의 관계
JavaScript 배열의 length 속성과 숫자 속성은 연결되어 있습니다.
내장 배열 메서드 중 일부(예: join(), slice(), indexOf() 등)는 호출 시 배열의 length 속성 값을 고려합니다.
다른 메서드(예: push(), splice() 등)도 배열의 length 속성을 갱신합니다.
const fruits = [];
fruits.push("banana", "apple", "peach");
console.log(fruits.length); // 3
속성이 유효한 배열 인덱스이고 해당 인덱스가 배열의 현재 범위를 벗어날 때 JavaScript 배열에 속성을 설정하면, 엔진은 배열의 length 속성을 적절히 갱신합니다.
fruits[5] = "mango";
console.log(fruits[5]); // 'mango'
console.log(Object.keys(fruits)); // ['0', '1', '2', '5']
console.log(fruits.length); // 6
length를 늘리면 새 요소를 만들지 않고 빈 슬롯을 추가하여 배열을 확장할 수 있습니다. undefined가 아닙니다.
fruits.length = 10;
console.log(fruits); // ['banana', 'apple', 'peach', empty x 2, 'mango', empty x 4]
console.log(Object.keys(fruits)); // ['0', '1', '2', '5']
console.log(fruits.length); // 10
console.log(fruits[8]); // undefined
그러나 length 속성을 줄이면 요소가 삭제됩니다.
fruits.length = 2;
console.log(Object.keys(fruits)); // ['0', '1']
console.log(fruits.length); // 2
length 페이지에서 더 자세히 설명하겠습니다.
배열 메서드와 빈 슬롯
희소 배열의 빈 슬롯은 배열 메서드 간에 일관성 없이 동작합니다. 일반적으로 오래된 메서드는 빈 슬롯을 건너뛰는 반면, 최신 메서드는 빈 슬롯을 undefined로 처리합니다.
여러 요소를 순회하는 메서드 중, 다음은 인덱스에 접근하기 전에 in 확인을 수행하여 빈 슬롯을 undefined로 취급하지 않습니다.
concat()copyWithin()every()filter()flat()flatMap()forEach()indexOf()lastIndexOf()map()reduce()reduceRight()reverse()slice()some()sort()splice()
빈 슬롯을 정확히 어떻게 처리하는지는 각 메서드의 페이지를 참조하세요.
아래 메서드는 빈 슬롯을 undefined로 취급합니다.
복사 메서드와 변경 메서드(mutating method)
일부 메서드는 메서드가 호출된 기존 배열을 변경하지 않는 대신, 새 배열을 반환합니다. 이러한 메서드는 먼저 새 배열을 구성한 다음 요소를 채우는 방식으로 수행됩니다. 복사는 항상 얕게 이루어지며, 메서드는 처음에 생성된 배열 이외에는 아무것도 복사하지 않습니다. 원래 배열의 요소는 다음과 같이 새 배열에 복사됩니다
- 객체: 객체 참조가 새 배열로 복사됩니다. 원래 배열과 새 배열 모두 동일한 객체를 참조합니다. 즉, 참조된 객체가 수정되면 변경 사항이 새 배열과 원래 배열 모두에 표시됩니다.
- 문자열, 숫자, 불리언과 같은 원시 유형(
String,Number,Boolean객체 아님): 해당 값이 새 배열에 복사됩니다.
어떤 메서드는 메서드가 호출된 배열을 변경하며, 이 경우 반환값은 메서드에 따라 다릅니다. 때로는 같은 배열에 대한 참조를 반환하고, 때로는 새 배열의 길이를 반환합니다.
다음 메서드는 this.constructor[Symbol.species]에 접근하여 사용할 생성자를 결정하고 새 배열을 생성합니다.
다음 메서드는 항상 Array 기본 생성자를 사용하여 새 배열을 생성합니다.
아래 표에는 원래 배열을 변경하는 메서드와 그에 상응하는 무변경 대체 메서드가 나열되어 있습니다.
| 변경 메서드 | 무변경 메서드 |
|---|---|
copyWithin() |
단일 메서드 대안 없음 |
fill() |
단일 메서드 대안 없음 |
pop() |
slice(0, -1) |
push(v1, v2) |
concat([v1, v2]) |
reverse() |
toReversed() |
shift() |
slice(1) |
sort() |
toSorted() |
splice() |
toSpliced() |
unshift(v1, v2) |
toSpliced(0, 0, v1, v2) |
변경 메서드를 무변경 대체 메서드로 변경하는 쉬운 방법은 전개 구문 또는 slice()를 사용하여 먼저 복사본을 만드는 것입니다.
arr.copyWithin(0, 1, 2); // arr을 변경함
const arr2 = arr.slice().copyWithin(0, 1, 2); // arr을 변경하지 않음
const arr3 = [...arr].copyWithin(0, 1, 2); // arr을 변경하지 않음
순회 메서드
많은 배열 메서드는 콜백 함수를 인수로 받습니다. 콜백 함수는 배열의 각 요소에 대해 순차적으로 최대 한 번만 호출되며, 콜백 함수의 반환값은 메서드의 반환값을 결정하는 데 사용됩니다. 이들은 모두 같은 모습을 공유합니다.
method(callbackFn, thisArg)
여기서 callbackFn은 세 개의 인수를 받습니다.
callbackFn이 반환할 것으로 예상되는 것은 호출된 배열 메서드에 따라 다릅니다.
callbackFn을 호출할 때 thisArg 인자(기본값은 undefined)는 this 값이 사용됩니다. callbackFn이 최종적으로 관찰할 수 있는 this 값은 일반적인 규칙에 따라 결정됩니다. callbackFn이 비엄격이라면, 원시 this 값은 객체로 래핑되고, undefined/null은 globalThis로 대체됩니다. 화살표 함수에는 자체 this 바인딩이 없으므로 thisArg 인자는 화살표 함수로 정의된 callbackFn과 관련이 없습니다.
모든 순회 메서드는 복사와 범용 메서드 이지만, 빈 슬롯에서는 다르게 동작합니다.
다음 메서드는 순회 메서드입니다.
특히, every(), find(), findIndex(), findLast(), findLastIndex(), some()는 모든 요소에 대해 항상 callbackFn을 호출하는 것이 아니라, 반환 값이 결정되는 즉시 순회를 중지합니다.
콜백 함수를 받아 배열의 각 요소에 대해 최대 한 번만 실행하는 다른 두 가지 메서드가 있지만, 일반적인 순회 메서드와는 약간 다른 모습을 가집니다(예: thisArg를 허용하지 않음).
sort() 메서드도 콜백 함수를 받지만, 순회 메서드는 아닙니다. 이 메서드는 배열을 제자리에서 변경하고, thisArg를 허용하지 않으며, 한 인덱스에서 콜백을 여러 번 호출할 수 있습니다.
범용 배열 메서드
배열 메서드는 항상 범용적이고, 이는 배열 객체의 내부 데이터에 접근하지 않습니다. length 속성과 인덱스된 요소를 통해서만 배열 요소에 접근합니다. 즉, 유사 배열 객체에서도 이 메서드를 호출할 수 있습니다.
const arrayLike = {
0: "a",
1: "b",
length: 2,
};
console.log(Array.prototype.join.call(arrayLike, "+")); // 'a+b'
length 속성 일반화
length 속성은 정수로 변환된 다음 0에서 253 - 1 사이의 범위로 고정됩니다. NaN은 0이 되므로, length가 없거나 undefined인 경우에도 0 값이 있는 것처럼 동작합니다.
이 언어는 length를 안전하지 않은 정수로 설정하지 못하도록 합니다. 모든 내장 메서드는 length가 253 - 1보다 큰 숫자로 설정될 때 TypeError를 발생시킵니다. 그러나 배열의 length 속성이 232 - 1보다 큰 값으로 설정되면 오류가 발생하기 때문에 배열이 아닌 객체에서 메서드를 호출하지 않는 한 일반적으로 안전한 정수 임곗값에 도달하지 못합니다.
Array.prototype.flat.call({}); // []
일부 배열 메서드는 배열 객체의 length 속성을 설정합니다. 이러한 메서드는 항상 일반화한 후 값을 설정하므로 length는 항상 정수로 끝납니다.
const a = { length: 0.7 };
Array.prototype.push.call(a);
console.log(a.length); // 0
유사 배열 객체
유사 배열 객체라는 용어는 위에서 설명한 length 변환 프로세스 중에 오류가 발생하지 않는 모든 객체를 의미합니다. 실제로 이러한 객체는 정말 length 속성을 가지며, 0에서 length - 1 범위의 인덱스 요소를 가질 것으로 예상됩니다. (모든 인덱스가 없는 경우, 기능적으로 희소 배열과 동일합니다.) 배열 메서드가 유사 배열 객체에서 작동할 때 0보다 작거나 length - 1보다 큰 정수의 인덱스는 무시됩니다.
많은 DOM 객체는 유사 배열입니다(예: NodeList와 HTMLCollection). arguments 객체도 유사 배열입니다. 유사 배열에 배열 메서드가 없더라도 배열 메서드를 호출할 수 있습니다.
function f() {
console.log(Array.prototype.join.call(arguments, "+"));
}
f("a", "b"); // 'a+b'
생성자
Array()-
새
Array객체를 생성합니다.
정적 속성
Array[@@species]-
Array생성자를 반환합니다.
정적 메서드
Array.from()-
순회 가능 또는 유사 배열 객체에서 새
Array인스턴스를 생성합니다. Array.fromAsync()-
비동기 순회 가능, 순회 가능, 또는 유사 배열 객체에서 새
Array인스턴스를 생성합니다. Array.isArray()-
인자가 배열이면
true를 반환하고, 그렇지 않으면false를 반환합니다. Array.of()-
인자의 개수나 유형에 관계없이 가변적인 수의 인자를 가진 새
Array인스턴스를 생성합니다.
인스턴스 속성
아래 속성은 Array.prototype에 정의되며 모든 Array 인스턴스에서 공유됩니다.
Array.prototype.constructor-
인스턴스 객체를 생성한 생성자 함수입니다.
Array인스턴스의 경우, 초기 값은Array생성자입니다. Array.prototype[@@unscopables]-
ES2015 버전 이전의 ECMAScript 표준에 포함되지 않았으며
with문 바인딩 목적으로 무시되는 속성 이름을 포함합니다.
아래 속성은 각 Array 인스턴스의 고유 속성입니다.
length-
배열 요소의 개수를 반영합니다.
인스턴스 메서드
Array.prototype.at()-
주어진 인덱스에 있는 배열의 항목을 반환합니다. 마지막 항목부터 셀 수 있는 음의 정수를 허용합니다.
Array.prototype.concat()-
다른 배열 및/또는 값과 결합된 호출 배열인 새 배열을 반환합니다.
Array.prototype.copyWithin()-
배열 내의 배열 요소 시퀀스를 복사합니다.
Array.prototype.entries()-
배열의 각 인덱스에 대한 키/값 쌍을 포함하는 새 배열 반복자 객체를 반환합니다.
Array.prototype.every()-
호출 배열의 모든 요소가 테스트 함수를 만족하면
true를 반환합니다. Array.prototype.fill()-
시작 인덱스부터 끝 인덱스까지 배열의 모든 요소를 고정된 값으로 채웁니다.
Array.prototype.filter()-
제공된 필터링 함수가
true를 반환하는 호출 배열의 모든 요소를 포함하는 새 배열을 반환합니다. Array.prototype.find()-
제공된 테스트 함수를 만족하는 배열의 첫 번째 요소의 값을 반환하고, 적절한 요소를 찾을 수 없으면
undefined를 반환합니다. Array.prototype.findIndex()-
제공된 테스트 함수를 만족하는 배열의 첫 번째 요소의 인덱스를 반환하고, 적절한 요소를 찾을 수 없으면
-1을 반환합니다. Array.prototype.findLast()-
제공된 테스트 함수를 만족하는 배열의 마지막 요소의 값을 반환하고, 적절한 요소를 찾을 수 없으면
undefined를 반환합니다. Array.prototype.findLastIndex()-
제공된 테스트 함수를 만족하는 배열의 마지막 요소의 인덱스를 반환하고, 적절한 요소를 찾을 수 없는 경우
-1을 반환합니다. Array.prototype.flat()-
지정된 깊이까지 재귀적으로 연결된 모든 하위 배열 요소가 포함된 새 배열을 반환합니다.
Array.prototype.flatMap()-
호출 배열의 각 요소에 지정된 콜백 함수를 적용한 다음 결과를 한 단계씩 평탄화하여 만들어진 새 배열을 반환합니다.
Array.prototype.forEach()-
호출 배열의 각 요소로 함수를 호출합니다.
Array.prototype.includes()-
호출하는 배열에 값이 포함되어 있는지 여부를 판단하여 적절하게
true나false를 반환합니다. Array.prototype.indexOf()-
호출 배열에서 지정된 요소를 찾을 수 있는 첫 번째(최소) 인덱스를 반환합니다.
Array.prototype.join()-
배열의 모든 요소를 문자열로 결합합니다.
Array.prototype.keys()-
호출 배열의 각 인덱스에 대한 키를 포함하는 새 배열 반복자를 반환합니다.
Array.prototype.lastIndexOf()-
호출 배열에서 지정된 요소를 찾을 수 있는 마지막(가장 큰) 인덱스를 반환하고, 찾을 수 없는 경우
-1을 반환합니다. Array.prototype.map()-
호출 배열의 모든 요소에 함수를 호출한 결과를 포함하는 새 배열을 반환합니다.
Array.prototype.pop()-
배열에서 마지막 요소를 제거하고 해당 요소를 반환합니다.
Array.prototype.push()-
배열 끝에 하나 이상의 요소를 추가하고, 배열의 새
length를 반환합니다. Array.prototype.reduce()-
배열의 각 요소(왼쪽에서 오른쪽으로)에 대해 사용자가 제공한 "리듀서" 콜백 함수를 실행하여 하나의 값으로 줄입니다.
Array.prototype.reduceRight()-
배열의 각 요소(오른쪽에서 왼쪽으로)에 대해 사용자가 제공한 "리듀서" 콜백 함수를 실행하여 하나의 값으로 줄입니다.
Array.prototype.reverse()-
배열 요소의 순서를 반대로 바꿉니다. (첫 번째가 마지막이 되고, 마지막이 첫 번째가 됩니다.)
Array.prototype.shift()-
배열에서 첫 번째 요소를 제거하고 해당 요소를 반환합니다.
Array.prototype.slice()-
호출 배열의 구획을 추출하고 새 배열을 반환합니다.
Array.prototype.some()-
호출 배열의 요소 중 하나 이상이 제공된 테스트 함수를 만족하면
true를 반환합니다. Array.prototype.sort()-
배열의 요소를 제자리 정렬하고 배열을 반환합니다.
Array.prototype.splice()-
배열에서 요소를 추가 및/또는 제거합니다.
Array.prototype.toLocaleString()-
호출 배열과 그 요소를 나타내는 지역화된 문자열을 반환합니다.
Object.prototype.toLocaleString()메서드를 재정의합니다. Array.prototype.toReversed()-
원래 배열을 수정하지 않고, 요소가 역순으로 배열된 새 배열을 반환합니다.
Array.prototype.toSorted()-
원래 배열을 수정하지 않고, 오름차순으로 정렬된 요소가 있는 새 배열을 반환합니다.
Array.prototype.toSpliced()-
원래 배열을 수정하지 않고, 지정된 인덱스에서 일부 요소를 제거 및/또는 교체한 새 배열을 반환합니다.
Array.prototype.toString()-
호출 배열과 그 요소를 나타내는 문자열을 반환합니다.
Object.prototype.toString()메서드를 재정의합니다. Array.prototype.unshift()-
배열 앞쪽에 하나 이상의 요소를 추가하고, 배열의 새
length를 반환합니다. Array.prototype.values()-
배열의 각 인덱스의 값을 포함하는 새 배열 순회자 객체를 반환합니다.
Array.prototype.with()-
원래 배열을 수정하지 않고, 지정된 인덱스의 요소를 지정된 값으로 바꾼 새 배열을 반환합니다.