Frontend 개발자 - hyo.loui

모던 javascript - 배열(Array) 본문

Javascript

모던 javascript - 배열(Array)

hyo.loui 2023. 3. 27. 02:30

❤️‍🔥TIL : Today I Learned

배열(Array)

배열은 여러 개의 값을 순차적으로 나열한 자료구조다.


배열이란?

 

우리가 JS에서 사용 빈도가 매우 높은 가장 기본적인 자료구조다.

자바스크립트는 배열을 다루기 위한 유용한 메서드를 다수 제공한다.

배열은 사용빈도가 매우 높으므로 배열 메서드를 능숙하게 다룰 수 있다면 코딩에 매우 도움이 된다.

 

const 배열명 = ['요소1', '요소2', '요소3'];

 

배열이 가지고 있는 값을 요소(element)라고 부른다.

배열의 요소는 자신의 위치를 나타내는 0 이상의 정수인 인덱스(index)를 갖는다.

 

대부분의 프로그래밍 언어에서 인덱스는 0부터 시작한다.

배열명[0] // '요소1'
배열명[1] // '요소2'
배열명[2] // '요소3'

 

배열이라는 타입은 존재하지 않는다. 배열은 객체 타입이다.

typeof arr // object

 

배열은 객체지만 일반 객체와는 구별되는 독특한 특징이 있다.

값의 순서와 length 프로퍼티를 갖기 때문에 index를 가지고 편하게 접근할 수 있다.

 


자바스크립트 배열은 배열이 아니다.

 

이게 무슨 소리인가 싶겠지만,

자료구조의 배열과 js에서 우리가 사용하는 배열(array)은 다른 것 이다.

 

- 자료구조에서 말하는 배열은 동일한 크기의 메모리공간이
  빈틈없이 연속적으로 나열된 자료구조를 말한다. 이러한 배열을 밀집 배열(dense array)이라고 한다.

 

- 자바스크립트의 배열은  일반적인 의미의 배열과 다르다.

  배열의 요소를 위한 각각의 메모리 공간은 동일한 크기를 갖지 않아도 되며, 연속적으로 이어져 있지 않을 수도 있다.

  배열의 요소가 연속적으로 이어져 있지 않은 배열 희소 배열(sparse array)이라 한다.

1)각각의 메모리 공간은 동일한 크기를 갖지 않아도 되며
2)연속적으로 이어져 있지 않을 수도 있는 희소 배열의 형태를 가진다.
   자바스크립트 배열은 엄밀히 말하면 일반적인 배열의 동작을 흉내 낸 특수 객체이다.

 

- 일반적인 배열은 인덱스로 요소에 빠르게 접근 가능하지만, 삽입과 삭제에 효율적이지 않다.

- 자바스크립트 배열은 해시테이블로 구현된 객체 이므로 일반적인 배열보다 성능면에서 느릴 수 밖에 없는 구조적인 단점이 있다. 하지만 삽입 또는 삭제하는 경우에는 일반적인 배열보다 빠른 성능을 기대할 수 있다.


length 프로퍼티와 희소 배열

 

length 프로퍼티는 요소의 개수, 즉 배열의 길이를 나타내는 0 이상의 정수를 값으로 갖는다.

빈 배열의 경우는 0이며, 빈배열이 아닐 경우 가장큰 인덱스에 1을 더한 것과 같다.

[].length   // 0
[1, 2, 3].length   // 3

length 프로퍼티의 값은 배열에 요소를 추가허나 삭제하면 자동 갱신 된다.

배열의 길이를 바탕으로 결정이 되지만 임의의 숫자를 값으로 명시적으로 할당 할 수 있다.

const 숫자배열 = [1,2,3,4,5]

숫자배열.length = 3;

console.log(숫자배열);  // [1,2,3]

 

하지만, 여기서 주의해야 할 것은 length 프로퍼티의 값보다 큰 숫자 값을 할당하는 경우다.

🚫 실제로 배열의 길이가 늘어나지 않는다.

 

const 배열 = [1];
배열.length = 3;

console.log(배열.length);  // 3
console.log(배열);  // [1, empty, empty]

length 프로퍼티 값은 변경되지만 실제 배열에는 변함이 없다.
(=값이 없는 비어있는 요소, empty를 위해 메모리 공간을 확보하지도 않으며, 요소를 생성하지도 않는다.

 

  • 이렇게 배열의 요소가 연속적으로 위치하지 않고 비어있는 배열 희소 배열이라 한다.
  • 자바스크립트는 희소 배열을 문법적으로 허용한다.

그래서, 일반적인 배열과 희소배열을 다시한번 비교해보자면

  • 일반적인 배열 : length는 배열의 요소의 개수(배열의 길이)와 언제나 일치한다.
  • 희소 배열 : length와 배열 요소의 개수가 일치하지 않고 희소배열의 length는 희소배열의 실제 요소 개수보다 언제나 크다.
    배열을 생성 시 희소배열을 생성하지 않도록 주의하자. 배열에는 같은 타입의 요소를 연속적으로 위치시키는 것이 최선이다.

 


배열 생성 - 4 가지 방법

 

 배열 리터럴


위에서 보았던 형태, 가장 일반적인 형태

const arr = [1,2,3];

+ 희소 배열

const arr = [1, ,3];

console.log(arr.length);  // 3
console.log(arr);  // [1, empty, 3]
console.log(arr[1]);  // undefined

 

 Array 생성자 함수

 

const arr = new Array(10);

console.log(arr);  // [empty * 10]
console.log(arr.length);  // 10

이 때 생성된 배열은 희소 배열이다. length는 0이 아니지만 실제로 배열의 요소는 존재하지 않는다.

 

 Array.of

 

전달된 인수를 요소로 갖는 배열을 생성한다.

Array.of(1);  // [1]

Array.of(1, 2, 3);  // [1, 2, 3]

Array.of('string');  // ['string'];

 

 Array.from

 

유사 배열 객체 또는 이터러블 객체를 인수로 전달받아 배열로 반환한다.

 

Array.from({ length: 2, 0: 'a', 1: 'b' });  // ['a', 'b']

Array.from("hello"); // ['h', 'e', 'l', 'l', 'o']

 


배열 요소의 참조

 

배열의 요소를 참조할 때에는 대괄호 [ ] 표기법을 사용한다.

대괄호 안에는 인덱스가 와야 한다. 정수로 평가되는 표현식 이라면, 인덱스 대신 사용할 수 있다.

 

const 이건배열 = [1, 2];

console.log(이건배열[0]);  // 1
cosnole.log(이건배열[1]);  // 2
console.log(이건배열[2]);  // undefined;

 

+ 희소 배열

const 희소배열 = [1, , 3];

console.log(Object.getOwnPropertyDescriptors(희소배열));
/*
{
  '0' : {value: 1, writable: true, enumerable: true, configurable: true},
  '2' : {value: 3, writable: true, enumerable: true, configurable: true},
  length : {value: 3, writable: true, enumerable: false, configurable: false}
}
*/

 


배열 요소의 추가와 갱신

 

존재하지 않는 인덱스를 사용해 값을 할당하면 새로운 요소가 추가된다.

이 때 length 프로퍼티 값은 자동 갱신된다.

const 배열이다 = [0];

배열이다[1] = 1;

console.log(배열이다);  // [0, 1]
console.log(배열이다.length);  // 2
// length는 자동 갱신

 

 

만약 현재 배열의 length 프로퍼티 값보다 큰 인덱스로 새로운 요소를 추가하면 희소 배열이 된다.

이 때 인덱스로 요소에 접근하여 명시적으로 값을 할당하지 않은 요소는 생성되지 않는다는 것에 주의하자.

즉 현재 배열에는 0번째 index 값100번째 인덱스 값 두개뿐 인 배열인 셈이다.

 


배열 요소의 삭제

 

배열은 사실 객체이기 때문에 배열의 특정 요소를 삭제하기 위해 delete 연산자를 사용할 수 있다.

하지만 권장하지 않는다.

const 배열이닷 = [1, 2, 3];

delete 배열이닷[1];

console.log(배열이닷);  // [1, empty, 3]

// length 프로퍼티에 영향 없고, 희소배열이 됨.
console.log(배열이닷.length);  // 3

 위처럼, 희소 배열이 되어 length 프로퍼티 값은 변하지 않아 delete 연산자는 사용하지 않는 것이 좋다.

 

따라서 배열의 특정 요소를 완전히 삭제하려면 Array.prototype.splice 메서드를 사용한다.

const 배열임 = [1, 2, 3];

배열임.splice(1, 1);
console.log(배열임);  // [1, 3]

// length 프로퍼티가 자동 갱신.
console.log(배열임.length); // 2

 


 

 최종 정리

  1. 배열이 가지고 있는 값을 요소(element), 자신의 위치를 나타내는 정수인 인덱스(index).
  2. 자료구조 배열은 밀집배열이며 삽입과 삭제에 비효율적, 자바스크립트 배열은 희소 배열이며 성능은 떨어지나 삽입과 삭제에 효율적.
  3. 배열요소의 참조는 [index]로 접근이 가능하고 추가와 갱신이 가능하다. 이때 length는 자동 갱신이 이루어진다.
  4. 배열은 객체이기 때문에 delete 연산자로 삭제가 가능하지만, 희소배열이 되기 때문에 .splice 메서드를 사용하여 삭제해야 한다.