JavaScript - 배열인듯 배열아닌 객체같은 배열에 대해서 알아보자!

*🔐Study Keyword :

배열이 🗝️무엇인지 🗝️왜 필요한지 🗝️어떻게 선언하는지에 대해서 알아보자

<목차>
1. 배열?
2. 배열은 배열이 아니다?
3. length 프로퍼티와 희소배열?

  • 배열은 사용빈도가 높아 배열을 다루기 위한 유용한 메서드들을 능숙하게 다룰 줄 알아야한다.

- 1. 배열

-WHAT IS❓

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

-HOW TO USE❕❓

  • 배열이 가지고 있는 값들요소(element)인데 자바스크립트의 모든 값(원시값, 객체, 함수, 배열 등)이 배열의 요소가 될 수 있다.
  • 배열의 요소는 배열에서 자신의 위치를 나타내는 0 이상의 정수인덱스를 갖고 이는 배열의 요소에 접근할 때 사용된다.
  • 요소에 접근할 때? 대괄호 [] 표기법을 사용해 접근하자고 하는 요소의 인덱스를 지정한다.
  • 배열은 배열의 길이(요소의 개수)를 나타내는 length 프로퍼티를 갖는다.
<script>
const arr = ['apple', 'banana', 'orange']
arr[1] // 'apple' 
arr[2] // 'banana'
arr[3] // 'orange'
arr.length // 3
</script>
  • 배열은 인덱스와 length 프로퍼티를 갖기 때문에 for문을 통해 순차적으로 요소에 접근할 수 가 있다.
  • 자바스크립트는 배열 역시 객체 타입이기에 배열 타입이 존재하지 않는다.
<script>
const arr = ['apple', 'banana', 'orange']
for(let i = 0; i < arr.length; i++) {
	console.log(arr[i]) // ['apple', 'banana', 'orange']
}
typeof arr// objext
</script>

<배열을 만드는 방법들>

  • 배열은 배열 리터럴, Array 생성자 함수. Array.of, Array.from 메서드로 생성할 수 있다.
  • 배열의 생성자 함수는 Array며, 배열의 프로토타입 객체는 Array.prototype가 배열을 위한 빌트인 메서드를 제공한다.
<script>
const arr = ['apple', 'banana', 'orange']
arr.constuructor === arr; // true; 배열의 생성자 함수 === arr
Object.getPrototypeOf(arr) === Array.prototype // true;
</script>
  • 배열은 객체지만 일반 객체와 배열을 구분하는 가장 명확한 차이는 '값의 순서(index)''length 프로퍼티'이다.
  • 인덱스로 표현되는 값의 순서length 프로퍼티를 갖는 배열은 '반복문'을 통해 순차적을 접근하기 적합한 자료구조다.
    (이미지 출처: 딥다이브 코어 자바스크립트 - 527쪽)
<script>
const arr = ['apple', 'banana', 'orange']

for(let i = 0; i < arr.length; i++) {
	console.log(arr[i]) // ['apple', 'banana', 'orange']
}
</script>

-> 배열이 값의 순서(인덱스)와 length 프로퍼티를 갖기 때문에 배열에 요소에 1>처음부터 순차적으로 요소에 접근하거나, 2>마지막부터 역순으로 또는 3>특정 위치부터 순차적으로 등 다양한 방식으로 요소에 접근 할 수 있다.


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

  • 자료 구조에서 말하는 배열1)동일한 크기의 메모리 공간이 2)빈틈없이 연속적으로 나열된 자료구조를 말한다.

  • 배열의 요소는 '하나의 데이터 타입으로 통일되어 있으며 서로 연속적으로 인접'하여 이러한 배열을 밀접 배열이라 한다.
    검색 대상 요소의 메모리 구조 = 배열의 시작 메모리 주소 + 인덱스 × 요소의 바이트 수
    -인덱스 0인 메모리 주소 : (1000 + 0×8) = 1000
    -인덱스 1인 메모리 주소 : (1000 + 1×8) = 1008
    -인덱스 2인 메모리 주소 : (1000 + 2×8) = 1016

  • 일반적인 의미의 배열은 밀접 배열의 형태로 인덱스를 통해 단 한 번의 연산으로 임의의 요소에 접근하여 효율적이며 고속으로 동작한다.

  • 하지만 정렬되지 않은 배열에서 특정한 요소를 검색해야하는 경우 선형검색을 해야하며 배열에 요소를 삽입하거나 삭제하는 경우 배열의 요소를 연속적으로 유지하기 위해 요소를 이동시켜야한다.

-WHAT IS❓

  • 자바스크립트의 배열배열의 요소를 위한 1)각각의 메모리 공간은 동일한 크기를 갖지 않아도 되며 2)연속적으로 이어져 있지 않을 수도 있는 희소 배열의 형태를 가진다.
  • 자바스크립트 배열은 엄밀히 말하면 일반적인 배열의 동작을 흉내 낸 특수 객체이다.
<script>
console.log(Object.getOwnPropertyDescriptors([1,2,3]));
//Object.getOwnPropertyDescriptors메서드를 사용해 프로퍼티 어트리뷰트를 확인할 수 있다.
/* 
{
'0' : {configurable: true, enumerable: true, value: 1, writable: true},
'1' : {configurable: true, enumerable: true, value: 1, writable: true},
'2' : {configurable: true, enumerable: true, value: 1, writable: true}, 
length: { configurable: false, enumerable: false, value: 3, writable: true}
}
*/
</script>
  • 자바스크립트 배열은 1>인덱스를 나타내는 문자열을 프로퍼티 키로 가지며 2>length 프로퍼티를 갖는 특수한 객체이다.
  • 이처럼 배열의 요소는 사실 프로퍼티의 값이다. 자바 스크립트에서 사용할 수 있는 모든 값은 객체의 프로퍼티 값이 될 수 있으므로 어떤 타입의 값이라도 배열의 요소가 될 수 있다.
<script>
const arr = [
  'string',
  10,
  true,
  null
  undefined,
  NaN,
  Infinity,
  [],
  {},
  function(){}    
];
</script>

<일반적인 배열 vs 자바스크립트의 배열 비교>

  • 일반적인 배열 :
    -[장] 인덱스로 요소에 빠르게 접근할 수 있다.
    -[단] 특정 요소를 검색하거나 요소를 삽입 또는 삭제하는 경우에 효율적이지 않다.
  • 자바스크립트 배열(해시 테이블로 구현된 객체) :
    -[단] 인덱스로 요소에 접근하는 경우 일반적인 배열보다 성능적인 면에서 느릴 수 밖에 없는 구조적 단점을 가진다.
    -[장]특정요소를 검색하거나 요소를 삽입 또는 삭제하는 경우엔 일반적인 배열보다 빠른 성능을 기대할 수 있다.

-3. length 프로퍼티와 희소배열

-WHAT IS❓

  • length 프로퍼티요소의 개수로 배열의 길이를 나타내는 0개 이상의 정수를 값으로 갖는다.
  • -length 프로퍼티는 빈 배열의 경우는 0이며 빈 배열이 아닌 경우 가장 큰 인덱스에 1을 더한 것과 같다.
<script>
[].length // 0
[1, 2, 3].length // 3
</script>

-HOW TO USE❕❓

  • length 프로퍼티의 값배열에 1>요소를 추가하거나 2>삭제하면 자동 갱신된다.
<script>
const arr = [1, 2, 3];
console.log(arr.length); // 3
// 1> 요소 추가
arr.push(4);
console.log(arr.length); // 4
// 2> 요소 삭제
arr.pop()
console.log(arr.length); // 3
</script>

<예시1>
-배열의 length 프로퍼티 값 > 요소의 개수 큰 경우

  • length 프로퍼티 값은 요소의 개수, 배열의 길이를 바탕으로 결정되지 않아 임의의 숫자 값을 명시적으로 할당할 수 있다.
<script>
const arr = [1, 2, 3, 4, 5];
arr.length = 3; // 현재 length 프로퍼티 값 5 보다 작은 숫자 값인 3을 할당한다.
console.log(arr); // [1, 2, 3], 배열의 길이가 5에서 3으로 줄어든다.
</script>

<예시2>
-배열의 length 프로퍼티 값 < 요소의 개수 큰 경우

🚫주의🚫) - length 프로퍼티 값 보다 큰 숫자를 할당하면 length 프로퍼티 값은 변경 되지만 실제로 배열의 길이가 늘어나지는 ❌

<script>
const arr = [1];
arr.length = 3;
//현재 length 프로퍼티 값 1 보다 큰 숫자 값 3 할당하면
console.log(arr.length); // 3, 프로퍼티의 값은 변경된다.
console.log(arr); // [1, empty * 2];, 하지만 실제로 배열의 길이가 늘어나진 않는다.
console.log(arr[1]); // undefined
</script>
  • 위 코드에 출력 결과인 empty x 2는 실제로 추가된 배열의 요소가 아닌 arr[1], arr[2]에 값이 존재하지 않는다는 것을 의미한다.
  • length 프로퍼티 값은 변경되지만 실제 배열에는 변함이 없다. (=값이 없는 비어있는 요소, empty를 위해 메모리 공간을 확보하지도 ❌ 요소를 생성하지도 ❌)

-WHAT IS❓

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

-HOW TO USE❕❓

<script>
//희소 배열
const sparse = [, 2, , 4]; 
//희소 배열의 length 프로퍼티 값(4)은 요소의 개수(2)와 일치하지 않고 언제나 크다!
//배열엔 인덱스가 0, 2인 요소가 존재하지 않는다는 뜻이다.
</script>

-일반적인 배열 VS 희소배열 비교

  • 일반적인 배열length는 배열 요소의 개수(배열의 길이)와 언제나 일치한다.
  • 희소 배열은 length와 배열 요소의 개수가 일치하지 않고 희소 배열의 length는 희소 배열의 실제 요소 개수보다 '언제나' 크다.
    -> 배열을 생성 시 희소 배열을 생성하지 않도록 주의🙆‍♂️ 배열은 💯같은 타입의 요소를 연속적으로 위치시키는 형태💯가 가장 좋당.

*💡conclusion

  • 자바스크립트의 배열은 일반적인 배열을 흉내낸 1>값의 순서(인덱스)와 2>length 프러퍼티를 지닌 특수한 객체에 가깝다.
  • 1>인덱스를 나타내는 문자열 = 프로퍼티 키 + 배열의 요소 = 프로퍼티 값 > 배열은 프로퍼티를 가진 객체
    2>length 프로퍼티를 가진 특수한 객체인 배열
    1> 값의 순서와 2>length 프로퍼티로 인해 배열의 요소에 순차적, 역순, 특정 요소부터 등(반복문도 OK)다양하게 접근이 가능하다.
  • 배열의 length 프로퍼티(배열의 길이) 값의 특징인 요소 추가 삭제시 자동 갱신 되는 점과 & length 프로퍼티의 값이 요소 개수 보다 크거나 작은 경우의 각각의 특징에 대해서
  • length 프로퍼티의 값이 요소 개수 보다 큰 경우 요소가 연속적으로 위치하지 않고 비어있는 배열인 희소 배열이되는데 일반적인 배열과 희소 배열의 차이가 있음을 명시!

#📑Study Source

  1. 책 - 모던 자바스크립트 Deep Dive: 자바스크립트의 기본 개념과 동작원리(492p-499p)

좋은 웹페이지 즐겨찾기