배열(Array)

SANGKU OH·2020년 6월 23일
post-thumbnail

배열

배열(array)은 1개의 변수에 여러 개의 값을 순차적으로 저장할 때 사용!
자바스크립트의 배열은 객체이며 유용한 내장 메소드를 포함하고 있다.

배열은 Array 생성자로 생성된 Array 타입의 객체이며 프로토타입 객체는 Array.prototype이다.

1. 배열의 생성

1-1. 배열 리터럴

  • 0개 이상의 값을 쉼표로 구분하여 대괄호([])로 묶는다.
  • 첫번째 값은 인덱스 ‘0’으로 읽을 수 있다.
  • 존재하지 않는 요소에 접근하면 undefined를 반환한다.

위의 배열을 객체 리터럴로 유사하게 표현하면 다음과 같다.

  • 배열 리터럴은 객체 리터럴과 달리 property명이 없고 각 요소의 값만 존재한다.
  • 객체는 property값에 접근하기 위해 대괄호 표기법 또는 마침표 포기법을 사용하며, propery명을 key로 사용한다.
  • 배열은 요소에 접근하기 위해 대괄호 표기법만을 사용하며, 대괄호 내에 접근하고자 하는 요소의 index를 넣어준다. index는 0부터 시작한다.
    두 객체의 근본적인 차이는 배열 리터럴arr의 prototype 객체는 Array.prototype이지만 객체 리터럴 obj의 prototype의 객체는 object.prototype이라는 것이다.


Javascript의 배열은 어떤 데이터 타입의 조합이라도 포함할 수 있다.

1-2. Array() 생성자 함수

  • 배열은 일반적으로 배열 리터럴 방식으로 생성하지만, 배열 리터럴 방식도 결국 내장함수 Array() 생성자 함수로 배열을 생성하는 것을 단순화시킨 것이다. Array() 생성자 함수는 Array.prototype.constructor 프로퍼티로 접근할 수 있다.
  • Array() 생성자 함수는 매개변수의 갯수에 따라 다르게 동작한다.
  • 매개변수가 1개이고 숫자인 경우 매개변수로 전달된 숫자를 length 값으로 가지는 빈 배열을 생성한다.

그 외의 경우는 매개변수로 전달된 값들을 요소로 가지는 배열을 생성한다.

2. 배열 요소의 추가와 삭제

2-1. 배열 요소의 추가

객체가 동적으로 property를 추가할 수 있는 것처럼 배열도 동적으로 요소를 추가할 수 있다.
이때 순서에 맞게 값을 할당할 필요는 없으며, index를 사용하여 필요한 위치에 값을 할당한다.
배열의 길이(length)는 마지막 index를 기준으로 산정된다.

값이 할당되지 않은 index 위치의 요소는 생성되지 않는 것에 주의!
단, 존재하지 않는 요소를 참조하면 undefined가 return된다.

2-2. 배열 요소의 삭제

배열은 객체이기 때문에 배열의 요소를 삭제하기 위해 delete 연산자를 사용하며, 이때 length에는 변함이 없다.
해당 요소를 완전히 삭제하여 length에도 반영되게 하기 위해서는 Array.prototype.splice 메소드를 사용한다.

3. 배열의 순회

객체의 프로퍼티를 순회할 때 for…in 문을 사용한다. 배열 역시 객체이므로 for…in 문을 사용할 수 있다.
그러나 배열은 객체이기 때문에 property를 가질 수 있다. for…in 문을 사용하면 배열 요소뿐만 아니라 불필요한 프로퍼티까지 출력될 수 있고 요소들의 순서를 보장하지 않으므로 배열을 순회하는데 적합하지 않다.

따라서 배열의 순회에는 forEach 메소드, for 문, for…of 문을 사용하는 것이 좋다.

4. Array Property

4-1 Array.length

length 프로퍼티는 요소의 개수(배열의 길이)를 나타낸다. 배열 인덱스는 32bit 양의 정수로 처리된다. 따라서 length 프로퍼티의 값은 양의 정수이며 232 - 1(4,294,967,296 - 1) 미만이다.


주의! 배열 요소의 개수와 length 프로퍼티 값이 반드시 일치하는 것은 아님!
현재 length 프로퍼티 값보다 더 큰 인덱스로 요소를 추가하면 새로운 요소를 추가할 수 있도록 자동으로 length 프로퍼티의 값이 늘어난다. length 프로퍼티의 값은 가장 큰 인덱스에 1을 더한 것과 같다.

length 프로퍼티의 값은 명시적으로 변경할 수 있다. 만약 length 프로퍼티의 값을 현재보다 작게 변경하면 변경된 length 프로퍼티의 값보다 크거나 같은 인덱스에 해당하는 요소는 모두 삭제된다.

5. Array Method

  • ✏️ method는 this(원본 배열)을 변경한다.
  • 🔒 method는 this(원본 배열을) 변경하지 않는다.

5-1. Array.isArray(arg: any): boolean (ES5)

정적 메소드 Array.isArray는 주어진 인수가 배열이면 true, 배열이 아니면 false를 return!

5-2. Array.from (ES6)

Array.from 메소드는 유사 배열 객체(array-like object) 또는 이터러블 객체(iterable object)를 변환하여 새로운 배열을 생성한다.

5-3. Array.of (ES6)

Array.of 메소드는 전달된 인수를 요소로 갖는 배열을 생성한다.
Array.of는 Array 생성자 함수와 다르게 전달된 인수가 1개이고 숫자이더라도 인수를 요소로 갖는 배열을 생성한다.

5-4. Array.prototype.indexOf(searchElement: T, fromIndex?: number): number (ES5) 🔒

원본 배열에서 인수로 전달된 요소를 검색하여 index를 반환한다.

  • 중복되는 요소가 있는 경우 => 첫번째 index를 반환한다.
  • 해당요소가 없는 경우 => -1을 반환한다.

indexOf 메소드는 배열에 요소가 존재하는지 여부를 확인할때 유용하다.

ES7에서 새롭게 도입된 Array.prototype.includes 메소드를 사용하면 보다 가독성이 좋다.👍

5-5. Array.prototype.concat(…items: Array<T[ ] | T>): T[ ] 🔒

인수로 전달된 값들(배열 또는 값)을 원본 배열의 마지막 요소로 추가한 새로운 배열을 반환한다. 인수로 전달한 값이 배열인 경우, 배열을 해체하여 새로운 배열의 요소로 추가한다. 원본 배열은 변경되지 않는다.

5-6. Array.prototype.join(separator?: string): string 🔒

원본 배열의 모든 요소를 문자열로 변환한 후, 인수로 전달받은 값, 즉 구분자(separator)로 연결한 문자열을 반환한다. 구분자(separator)는 생략 가능하며 기본 구분자는 ,이다.

5-7. Array.prototype.push(…items: T[]): number ✏️

인수로 전달받은 모든 값을 원본 배열의 마지막에 요소로 추가하고 변경된 length 값을 반환한다. push 메소드는 원본 배열을 직접 변경한다.

push 메소드와 concat 메소드는 유사하지만 미묘한 차이가 있다!
push 메소드 = 원본 배열을 직접변경
concat 메소드 = 원본 배열 변경 ❌ 새로운 배열 반환.

인수로전달받은 값이 배열인 경우
push 메소드 = 배열을 그대로 원본 배열의 마지막 요 소로 추가
concat 메소드 = 배열을 해체하여 새로운 배열의 마지막 요소로 추가

**push 메소드는 성능면에서 좋지 않다.
push 메소드는 배열의 마지막에 요소를 추가하므로 length property를 사용하여 직접 요소를 추가할 수 있다. 이 방법이 push 메소드보다 빠름!

push 메소드는 원본 배열을 직접 변경하는 부수 효과가 있다. 따라서 push 메소드보다는 ES6의 spread 문법을 사용하는 편이 좋다. 👍

5-8. Array.prototype.pop(): T | undefined ✏️

원본 배열에서 마지막 요소를 제거하고 제거한 요소를 반환한다.
원본 배열이 빈 배열이면 undefined를 반환한다. pop 메소드는 원본 배열을 직접 변경한다.

pop 메소드와 push 메소드를 사용하면 스택을 쉽게 구현할 수 있다!

스택(stack)은 데이터를 마지막에 밀어 넣고, 마지막에 밀어 넣은 데이터를 먼저 꺼내는 후입 선출(LIFO - Last In First Out) 방식의 자료 구조이다. 스택은 언제나 가장 마지막에 밀어 넣은 최신 데이터를 취득한다. 스택에 데이터를 밀어 넣는 것을 푸시(push)라 하고 스택에서 데이터를 꺼내는 것을 팝(pop)이라고 한다.

5-9. Array.prototype.reverse( ): this ✏️

배열 요소의 순서를 반대로 변경한다. 이때 원본 배열이 변경된다. 반환값은 변경된 배열이다.

5-10. Array.prototype.shift( ): T | undefined ✏️

배열에서 첫요소를 제거하고 제거한 요소를 반환한다. 만약 빈 배열일 경우 undefined를 반환한다. shift 메소드는 대상 배열 자체를 변경한다.

shift는 push와 함께 배열을 큐(FIFO: First In First Out)처럼 동작하게 한다.

Array.prototype.pop()은 마지막 요소를 제거하고 제거한 요소를 반환한다.

5-11. Array.prototype.slice(start=0, end=this.length): T[ ] 🔒

인자로 지정된 배열의 부분을 복사하여 반환한다. 원본 배열은 변경되지 않는다.

첫번째 매개변수 start에 해당하는 인덱스를 갖는 요소부터 매개변수 end에 해당하는 인덱스를 가진 요소 전까지 복사된다.

매개변수

  • start: 복사를 시작할 index, 음수인 경우 배열의 끝에서의 index를 나타낸다.
    ex) slice(-2)는 배열의 마지막 2개의 요소를 return한다.
  • end: 옵션이며, 기본값은 length 값이다.


slice 메소드에 인자를 전달하지 않으면 원본 배열의 복사본을 생성하여 반환한다.

이 때, 원본 배열의 각 요소를 얕은 복사(shallow copy)하여 새로운 복사본을 생성한다.

ES6에서 유사 배열 객체를 배열로 변환하는 방법은 아래와 같다.

5-12. Array.prototype.splice(start: number, deleteCount=this.length-start, …items: T[ ]): T[ ] ✏️

기존 배열의 요소를 제거하고 그 위치에 새로운 요소를 추가한다.
배열 중간에 새로운 요소를 추가할 때도 사용된다.

매개변수

  • start: 배열에서의 시작위치. start만 지정할 경우 배열의 start부터 모든 요소를 제거한다.
  • deleteCount: start부터 제거할 요소의 수 이다. deleteCount가 0인 경우, 아무런 요소도 제거되지않는다.(optional)
  • items: 삭제한 위치에 추가될 요소들이다. 만약 아무런 요소도 지정하지 않을 경우, 삭제만 한다.(optional)

이 메소드의 가장 일반적인 사용은 배열에서 요소를 삭제할 때


배열에서 요소를 제거하고 제거한 위치에 다른 요소를 추가한다.

배열 중간에 배열의 요소들을 해체하여 추가할 때도 사용된다.

⚡️ slice는 배열의 일부분을 복사해서 반환 = 원본을 훼손하지 않는다.
⚡️ splice는 배열에서 요소를 제거하고 제거한 위치에 다른 요소를 추가 = 원본을 훼손한다.

rel(https://poiemaweb.com/js-array)

profile
Prof.Google을 통해 필요한 정보를 이 곳에 insert 🐸

0개의 댓글