배열 메서드
Array 생성자 함수는 정적 메서드를 제공하며, 배열 객체의 프로토타입인 Array.prototype은 프로토타입 메서드를 제공한다.
배열 메서드는 결과물을 반환하는 패턴이 두 가지이다.
- 원본 배열(배열 메서드를 호출한 배열, 즉 배열 메서드의 구현체 내부에서 this가 가리키는 객체)을 직접 변경하는 메서드(mutator method)
- 원본 배열을 직접 변경하지 않고 새로운 배열을 생성하여 반환하는 메서드(accessor method)
1 | const arr = [1]; |
원본 배열을 직접 변경하는 메서드는 외부 상태를 직접 변경하는 부수 효과가 있으므로 사용할 때 주의해야 한다. 따라서 가급적 원본 배열을 직접 변경하지 않는 메서드(accessor method)를 사용하는 편이 좋다.
Array.isArray
Array.isArray 메서드는 전달된 인수가 배열이면 true, 배열이 아니면 false를 반환한다.
1 | // true |
Array.prototype.indexOf
indexOf 메서드는 원본 배열에서 인수로 전달된 요소를 검색하여 인덱스를 반환한다.
- 원본 배열에 인수로 전달한 요소와 중복되는 요소가 여러 개 있다면 첫 번째로 검색된 요소의 인덱스를 반환한다.
- 원본 배열에 인수로 전달한 요소가 존재하지 않으면 -1을 반환한다.
1 | const arr = [1, 2, 2, 3]; |
Array.prototype.push
인수로 전달받은 모든 값을 원본 배열의 마지막 요소로 추가하고 변경된 length 프로퍼티 값을 반환한다. push 메서드는 원본 배열을 직접 변경한다.
1 | const arr = [1, 2]; |
push 메서드는 성능 면에서 좋지 않다. 마지막 요소로 추가할 요소가 하나뿐이라면 push 메서드를 사용하지 않고 length 프로퍼티를 사용하여 배열의 마지막에 요소를 직접 추가할 수도 있다. 이 방법이 push 메서드보다 빠르다.
1 | const arr = [1, 2]; |
push 메서드는 원본 배열을 직접 변경하는 부수 효과가 있다. 따라서 push 메서드보다는 ES6의 스프레드 문법을 사용하는 편이 좋다. 스프레드 문법을 사용하면 함수 호출 없이 표현식으로 마지막에 요소를 추가할 수 있으며 부수 효과도 없다.
1 | const arr = [1, 2]; |
Array.prototype.pop
원본 배열에서 마지막 요소를 제거하고 제거한 요소를 반환한다. 원본 배열이 빈 배열이면 undefined를 반환한다. pop 메서드는 원본 배열을 직접 변경한다.
1 | const arr = [1, 2]; |
Array.prototype.unshift
인수로 전달받은 모든 값을 원본 배열의 선두에 요소로 추가하고 변경된 length 프로퍼티 값을 반환한다. unshift 메서드는 원본 배열을 직접 변경한다.
1 | const arr = [1, 2]; |
unshift 메서드는 부수 효과가 있다. 따라서 ES6의 스프레드 문법을 사용하는 편이 좋다. 스프레드 문법을 사용하면 함수 호출 없이 표현식으로 선두에 요소를 추가할 수 있으며 부수 효과도 없다.
1 | const arr = [1, 2]; |
Array.prototype.shift
원본 배열에서 첫 번째 요소를 제거하고 제거한 요소를 반환한다. 원본 배열이 빈 배열이면 undefined를 반환한다. shift 메서드는 원본 배열을 직접 변경한다.
1 | const arr = [1, 2]; |
shift 메서드와 push 메서드를 사용하면 큐를 쉽게 구현할 수 있다.
Array.prototype.concat
인수로 전달된 값들(배열 또는 원시값)을 원본 배열의 마지막 요소로 추가한 새로운 배열을 반환한다. 인수로 전달한 값이 배열인 경우 배열을 해체하여 새로운 배열의 요소로 추가한다. 원본 배열은 변경되지 않는다.
1 | const arr1 = [1, 2]; |
push와 unshift 메서드는 concat 메서드로 대체할 수 있다.
1 | const arr1 = [3, 4]; |
concat 메서드는 ES6의 스프레드 문법으로 대체할 수 있다.
1 | let result = [1, 2].concat([3, 4]); |
Array.prototype.splice
원본 배열의 중간에 요소를 추가하거나 중간에 있는 요소를 제거하는 경우 splice 메서드를 사용한다. splice 메서드는 3개의 매개변수가 있으며 원본 배열을 직접 변경한다.
start: 원본 배열의 요소를 제거하기 시작할 인덱스다. start만 지정하면 원본 배열의 start부터 모든 요소를 제거한다. start가 음수인 경우 배열의 끝에서의 인덱스를 나타낸다. 만약 start가 -1이면 마지막 요소를 가리키고 -n이면 마지막에서 n번째 요소를 가리킨다.
deleteCount: 원본 배열의 요소를 제거하기 시작할 인덱스인 start부터 제거할 요소의 개수다. deleteCount가 0인 경우 아무런 요소도 제거되지 않는다(옵션).
items: 제거한 위치에 삽입할 요소들의 목록이다. 생략할 경우 원본 배열에서 요소들을 제거하기만 한다(옵션).
1 | const arr = [1, 2, 3, 4]; |
splice 메서드의 두 번째 인수, 즉 제거할 요소의 개수를 0으로 지정하면 아무런 요소도 제거하지 않고 새로운 요소들을 삽입한다.
1 | const arr = [1, 2, 3, 4]; |
splice 메서드의 두 번째 인수, 즉 제거할 요소의 개수를 생략하면 첫 번째 인수로 전달된 시작 인덱스부터 모든 요소를 제거한다.
1 | const arr = [1, 2, 3, 4]; |
배열에서 특정 요소를 제거하려면 indexOf 메서드를 통해 특정 요소의 인덱스를 취득한 다음 splice 메서드를 사용한다.
1 | const arr = [1, 2, 3, 1, 2]; |
filter 메서드를 사용하여 특정 요소를 제거할 수도 있다. 하지만 특정 요소가 중복된 경우 모두 제거된다.
1 | const arr = [1, 2, 3, 1, 2]; |
Array.prototype.slice
인수로 전달된 범위의 요소들을 복사하여 배열로 반환한다. 원본 배열은 변경되지 않는다.
slice 메서드는 두 개의 매개변수를 갖는다.
start : 복사를 시작할 인덱스다. 음수인 경우 배열의 끝에서의 인덱스를 나타낸다. 예를 들어 slice(-2)는 배열의 마지막 두 개의 요소를 복사하여 배열로 반환한다.
end : 복사를 종료할 인덱스다. 이 인덱스에 해당하는 요소는 복사되지 않는다. end는 생략 가능하며 생략 시 기본값은 length 프로퍼티 값이다.
1 | const arr = [1, 2, 3]; |
이때 생성된 복사본은 얕은 복사(shallow copy)를 통해 생성된다.
1 | const todos = [ |
slice 메서드가 복사본을 생성하는 것을 이용하여 arguments, HTMLCollection, NodeList와 같은 유사 배열 객체(array-like object)를 배열로 변환할 수 있다.
1 | function sum() { |
Array.from 메서드를 사용하면 더욱 간단하게 유사 배열 객체를 배열로 변환할 수 있다. Array.from 메서드는 유사 배열 객체 또는 이터러블 객체를 배열로 변환한다.
1 | function sum() { |
rguments 객체는 유사 배열 객체이면서 이터러블 객체다. 이터러블 객체는 ES6의 스프레드 문법을 사용하여 간단하게 배열로 변환할 수 있다.
1 | function sum() { |
Array.prototype.join
원본 배열의 모든 요소를 문자열로 변환한 후, 인수로 전달받은 문자열, 즉 구분자(separator)로 연결한 문자열을 반환한다. 구분자는 생략 가능하며 기본 구분자는 콤마(‘,’)다.
1 | const arr = [1, 2, 3, 4]; |
Array.prototype.reverse
원본 배열의 순서를 반대로 뒤집는다. 이때 원본 배열이 변경된다. 반환값은 변경된 배열이다.
1 | const arr = [1, 2, 3]; |
Array.prototype.fill
인수로 전달받은 값을 배열의 처음부터 끝까지 요소로 채운다. 이때 원본 배열이 변경된다.
1 | const arr = [1, 2, 3]; |
fill 메서드를 사용하면 배열을 생성하면서 특정 값으로 요소를 채울 수 있다.
1 | const arr = new Array(3); |
fill 메서드로 요소를 채울 경우 모든 요소를 하나의 값만으로 채울 수밖에 없다는 단점이 있다. 하지만 Array.from 메서드를 사용하면 두 번째 인수로 전달한 콜백 함수를 통해 요소값을 만들면서 배열을 채울 수 있다.
1 | // 인수로 전달받은 정수만큼 요소를 생성하고 0부터 1씩 증가하면서 요소를 채운다. |
Array.prototype.includes
includes 메서드는 배열 내에 특정 요소가 포함되어 있는지 확인하여 true 또는 false를 반환한다. 첫 번째 인수로 검색할 대상을 지정한다.
1 | const arr = [1, 2, 3]; |
두 번째 인수로 검색을 시작할 인덱스를 전달할 수 있다. 두 번째 인수를 생략할 경우 기본값 0이 설정된다. 만약 두 번째 인수에 음수를 전달하면 length 프로퍼티 값과 음수 인덱스를 합산하여(length + index) 검색 시작 인덱스를 설정한다.
1 | const arr = [1, 2, 3]; |
indexOf 메서드를 사용하면 반환값이 -1인지 확인해 보아야 하고 배열에 NaN이 포함되어 있는지 확인할 수 없다는 문제가 있다.
1 | [NaN].indexOf(NaN) !== -1; // -> false |
Array.prototype.flat
flat 메서드는 인수로 전달한 깊이만큼 재귀적으로 배열을 평탄화한다.
1 | [1, [2, 3, 4, 5]].flat(); // -> [1, 2, 3, 4, 5] |
중첩 배열을 평탄화할 깊이를 인수로 전달할 수 있다. 인수를 생략할 경우 기본값은 1이다. 인수로 Infinity를 전달하면 중첩 배열 모두를 평탄화한다.
1 | // 중첩 배열을 평탄화하기 위한 깊이 값의 기본값은 1이다. |
참고 도서: 모던 자바스크립트 Deep Dive