Javascript 34장 - 배열과 배열 메서드
포스트
취소

Javascript 34장 - 배열과 배열 메서드

Javascript

  • 처음부터 다시 보는 딥 다이브

자바스크립트의 배열

  • 자바스크립트에서 배열이란 타입은 존재하지 않으며, 배열 또한 객체 타입이다.
  • 배열은 객체이지만 일반 객체와는 구분되는 차이점이 존재한다.
    • 객체는 프로퍼티와 키 값을 가지지만, 배열은 인덱스와 요소를 가진다.
    • 객체는 프로퍼티 키를 참조하여 값을 나타내지만, 배열은 인덱스를 참조하여 값을 나타낸다.
    • 객체는 값의 순서를 갖지 않지만, 배열은 값의 순서를 갖는다.
    • 객체는 length 프로퍼티를 갖지 않지만, 배열은 갖는다.

자바스크립트 배열의 특징

  • 배열은 두 가지로 구분된다.
    • 밀집 배열과 희소 배열로 구분된다.

밀집 배열

  • 자료구조에서 일반적으로 언급하는 동일한 크기의 메모리 공간이 빈틈없이 연속적으로 나열된 자료 구조를 말한다.
  • 배열의 요소들은 하나의 데이터 타입으로 통일, 서로 연속적으로 인접해 있는 형태를 의미한다.
  • 연속적인 구조이기 때문에, 인덱스를 통해 단 한 번의 연산으로 요소에 접근할 수 있다.
  • 정렬되지 않은 배열의 특정 요소를 검색하는 경우, 배열의 모든 요소를 처음부터 원하는 요소를 찾을 때까지 순회해야 하므로 시간 복잡도가 증가한다.
  • 배열의 요소를 삭제하거나 삽입하는 경우에도 연속적인 구조를 유지하기 위해 요소를 작업 시마다 이동시켜야 하는 단점이 존재한다.

희소 배열

  • 배열의 요소들이 각각의 메모리 공간의 크기가 동일하지 않아도 되고, 연속적으로 이루어져 있지 않아도 된다.
  • 이를 희소 배열이라고 하며 자바스크립트의 배열은 희소 배열이다.
    • 자바스크립트의 배열은 일반적인 배열의 동작을 흉내낸 특수한 객체이다.
  • 자바스크립트 배열은 인덱스를 나타내는 문자열을 프로퍼티 키로 가지며, length 프로퍼티를 갖는 특수한 객체이다.
  • 배열의 요소는 사실상 프로퍼티 값이며, 자바스크립트에서 사용할 수 있는 모든 값은 객체의 프로퍼티 값이 될 수 있으므로 어떤 타입의 값도 배열의 요소가 될 수 있다.

length 프로퍼티와 희소 배열

  • 기본적으로는 배열의 길이를 바탕으로 결정되지만, 임의의 숫자값을 명시적으로 할당할 수도 있다.
    • 이 경우, 현재 프로퍼티의 length 프로퍼티보다 작은 숫자 값을 할당할 경우 배열의 길이가 줄어든다.
    • 현재 프로퍼티의 length 프로퍼티 값보다 큰 숫자 값을 할당할 경우는 length 프로퍼티 값은 변경되지만 실제 배열의 길이는 변함이 없다.
    • length 프로퍼티가 값 없이 비어있는 요소를 위해 메모리 공간을 확보하지 않으며, 빈 요소를 생성하지 않음을 의미한다.
  • 배열의 요소가 연속적으로 위치하지 않고 일부가 비어 있는 배열인 희소 배열이다.
    • 자바스크립트 엔진은 희소 배열을 문법적으로 허용한다.
    • 희소 배열을 의도적으로 생성하는 일은 많지 않으며 가능한 사용하지 않는 것이 좋다.
    • 배열에는 같은 타입의 요소를 의도적으로 연속시켜 배치하는 것이 좋다.

배열 생성

new Array

  • 전달된 인수가 1개이고 숫자일 경우, length 프로퍼티 값이 인수인 배열을 생성한다.
  • 전달된 인수가 없는 경우, 빈 배열을 생성한다.
  • 전달된 인수가 2개 이상이거나 숫자가 아닌 경우, 인수를 요소로 갖는 배열을 생성한다.
1
2
3
4
5
new Array(); // []
new Array(3); // [<3 empty items>]
new Array(-1); // RangeError
new Array(1, 2, 3); // [1,2,3]
new Array({}); // [{}]

Array.of

  • ES6에 도입되었다.
  • 전달된 인수를 갖는 배열을 생성한다.
  • 인수가 1개이고 숫자여도 인수를 요소로 갖는 배열을 생성한다.
1
2
3
Array.of(1); // [1]
Array.of(1, 2, 3); // [1,2,3]
Array.of("arr"); // ["arr"]

Array.from

  • ES6에 도입되었다.
  • 유사 배열 객체 또는 이터러블 객체를 인수로 전달받아 배열로 변환 후 반환한다.
  • 두 번째 인수로 함께 전달할 콜백 함수를 통해 값을 만들면서 요소를 채울 수도 있다.
1
2
3
Array.from({ legnth: 2, 0: "1", 1: "2" }); // [1,2]
// 문자열은 이터러블 객체이기도 하다.
Array.from("Hi"); // ["H","i"]

배열 참조

  • 배열에 대괄호를 사용하며 인덱스를 삽입한다.
  • 정수로 평가되는 표현식이면 인덱스로 사용이 가능하다.
  • 존재하지 않는 요소에 접근하면 undefined를 반환한다.
1
arr[1];

배열 요소의 추가,갱신,삭제

  • 배열도 객체이므로 객체의 프로퍼티 동작으로 추가할 수 있는 것처럼 배열에도 요소를 동적으로 추가할 수 있다.
  • 현재 배열의 length 프로퍼티 값보다 큰 인덱스로 새로운 요소를 추가하려고 하면 희소 배열이 된다.
    • 값이 할당되지 않은 희소 배열의 요소들은 생성되지 않는다.
    • length 프로퍼티 값은 변하나 실질적인 배열 안의 요소 개수에는 변함이 없다.
  • 0 이상의 정수로 인덱싱에 사용해야 한다.
    • 정수 이외의 값을 인덱싱에 사용하면 요소가 생성되는 것이 아니라 프로퍼티가 생성된다.
    • 프로퍼티는 length 프로퍼티 값에 영향을 주지 않는다.
  • 배열도 객체이므로 배열의 특정 요소를 삭제하기 위해 delete 연산자를 사용할 수 있다.
    • delete 연산자를 통해 배열의 요소를 삭제하는 것은 객체의 프로퍼티를 삭제하는 것과 동일하다.
    • 요소의 값이 삭제되면 희소 배열이 된다.
    • 이 때, length 프로퍼티에는 영향을 주지 않는다.
  • 희소 배열을 만들지 않으면서 요소를 삭제하고 싶은 경우 Array.prototype.splice를 사용한다.

배열 메서드

  • mutator, accessor 메서드로 나뉜다.
    • mutator : 호출한 원본 배열을 직접 변경한다.
    • accessor : 원본 배열을 직접 변경하지 않고 새로운 배열을 반환한다.
  • 자바스크립트 배열은 다양한 빌트인 함수를 제공한다.
  • 배열 생성자 함수는 다양한 정적 메서드를 제공한다.
  • 배열 객체의 Array.prototype은 프로토타입을 제공한다.
  • 결과물을 반환하는 패턴은 두가지이다.
    • 원본 배열을 직접 변경하는 메서드는 외부 상태를 변경하는 사이드 이펙트를 발생시킬 수 있기 때문에 주의해야 한다.
    • 원본 배열을 직접 변경하지 않고 새로운 배열을 생성하여 반환하는 메서드를 사용하는 편이 좋다.

Array.isArray

  • 생성자 함수의 정적 메서드, 전달되는 인수가 배열인지를 판단한다.

Array.prototype.indexOf

  • 원본 배열에서 인수로 전달한 요소를 검색하여 인덱스를 반환한다.
  • 검색하는 요소의 첫 번째 요소를 반환한다.
  • 요소가 존재하지 않으면 -1을 반환하여 요소가 존재하는지 확인하는 데 유용하다.
1
2
3
4
const arr = [1, 2, 3];

arr.indexOf(-1); // 존재하지 않는 요소를 검색한다.
arr.indexOf(2, 2); // 두 번째 인덱스 2를 검색한다.

Array.prototype.push

  • mutator method
  • 인수로 전달받은 모든 값을 배열의 마지막 요소로 추가한다.
  • 변경된 length 프로퍼티를 반환한다.
  • 스프레드 문법을 사용하는 것이 더 좋다.
  • 객체에 스프레드 문법을 사용하여도 프로토타입 체인의 속성을 복사하진 않는다.

Array.prototype.pop

  • mutator method
  • 원본에서 마지막 요소를 제거하고 제거한 요소를 반환한다.
  • 원본 배열이 빈 배열이면 undefined를 반환한다.

Array.prototype.unshift

  • mutator method

  • 인수로 전달받은 모든 값을 배열의 선두에 추가하고, 변경된 length 프로퍼티 값을 반환한다.

Array.prototype.shift

  • mutator method

  • 원본 배열에서 첫 번째 요소를 제거하고 제거한 요소를 반환한다.
  • 원본 배열이 빈 배열이면 undefined를 반환한다.

Array.prototype.concat

  • 인수로 전달된 값들을 원본 배열의 마지막에 요소로 추가한 새로운 배열을 반환한다.
  • 인수로 전달한 값이 배열일 경우, 배열을 해체하여 새로운 배열을 반환한다.
  • push, unshift 메서드는 concat으로 대체 가능하다.
  • 원본 배열을 직접 변경하지 않고, 새로운 배열을 반환한다.
  • 스프레드 문법으로 대체 가능하다.

Array.prototype.splice

  • 원본 배열의 중간에 요소를 추가하거나 중간에 있는 요소를 제거할 때 사용한다.
  • 3개의 매개변수를 갖는데, 첫 번째에는 삭제 시작 인덱스, 두 번째에는 시작 인덱스로부터 삭제할 요소의 개수, 세 번째에는 요소를 삭제 후 인덱스로부터 추가할 데이터를 받는다.
1
2
const arr = [1, 2, 3, 4];
const newArr = arr.splice(1);

Array.prototype.slice

  • accessor method

  • 인수로 전달된 범위의 요소들을 복사하여 배열로 반환한다.
  • 두 개의 매개변수를 가지며, 첫 번째 인수로는 복사를 시작할 인덱스, 두 번째 인수로는 복사 끝 인덱스를 나타낸다.
  • 얕은 복사를 통해 새로운 배열을 생성한다.

Array.prototype.join

  • 원본 배열의 모든 요소를 문자열로 반환한 후, 인수로 전달받은 문자열, 즉 구분자로 연결하여 문자열을 반환한다.
1
2
3
4
const arr = [1, 3, 3, 5];

arr.join(); // 1,3,3,5
aarr.join(""); // 1335

Array.prototype.reverse

  • mutator method

  • 원본 배열의 순서를 반대로 뒤집는다.

Array.prototype.fill

  • mutator method
  • ES6에 도입
  • 인수로 전달받은 값으로 배열의 처음부터 끝까지 채운다.
  • 3개의 매개변수를 받는데, 첫 번째는 초기화 시킬 값, 두 번째는 시작 인덱스, 세 번째는 끝 인덱스 값을 입력한다.
1
2
3
const arr = new Array(3); // [<3 empty items>]
arr.fill(1); // [1,1,1]
arr.fill(100, 1, 2);

Array.prototype.includes

  • ES7에 도입
  • 배열 내에 특정 요소가 포함되어 있는지 확인하여 boolean 값을 반환한다.
  • 2개의 매개 변수를 가지며, 첫 번째는 검색할 값, 두 번째는 시작 인덱스를 입력한다.
  • indexOf와의 차이점은 indexOf는 없으면 -1임을 확인해야 하며, 배열에 NaN이 있다면 판별할 수 없다.
1
2
[NaN].indexOf(NaN); // -1
[NaN].includes(NaN); // true

Array.prototype.flat

  • ES10에 도입
  • 인수로 전달한 깊이만큼 재귀적으로 평탄화한다.
  • 기본값은 1이기 때문에 아무것도 전달하지 않으면 한 번 평탄화를 진행한다.
  • 인수로 Infinity를 전달하면 전부 평탄화한다.
1
2
3
const arr = [1, 1, 1, [2, 2, 2, [3, 3, 3]]];
const newArr1 = arr.flat(); // [1,1,1,2,2,2,[3,3,3]]
const newArr2 = arr.flat(2); // [1,1,1,2,2,2,3,3,3]
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.