[JS 자료구조] 배열

­Elena·2021년 11월 29일

[모던 자바스크립트 -> 코어 자바스크립트 -> 자료구조와 자료형]
아래는 링크를 정리한 내용입니다.

객체 복습

객체란 키를 사용해 식별할 수 있는 값을 담은 컬렉션이다.
하지만 객체는 순서를 고려하지 않고 만들어진 자료구조이기 때문에 순서가 있는 컬렉션이 필요할 때 사용하기 어렵다. (새로운 프로퍼티를 기존 프로퍼티 '사이에' 끼워 넣는 것 불가능) 이럴 땐 순서가 있는 컬렉션을 저장할 때는 쓰는 자료구조인 배열을 사용한다.

배열이란

배열은 특수한 형태의 객체로 순서가 있는 자료를 저장하고 관리하는 용도에 최적화된 자료구조이다.

배열 사용하기

배열의 선언

let arr = new Array();	//잘 사용하지 않음
let arr = [];
let fruits = ["사과", "오렌지", "자두"];	//초기화

특정 요소 얻기

let fruits = ["apple", "orange", "plum"];

alert(fruits[0]);	//apple
alert(fruits[1]);	//orange
alert(fruits[2]);	//plum

요소 수정하기

fruits[2] = "pear"	//배열이 ["apple", "orange", "pear"]로 바뀜

요소 추가하기

fruits[3] = "lemon"	//배열이 ["apple", "orange", "pear", "lemon"]으로 바뀜

요소 개수 알아내기 (length)

let fruits = ["apple", "orange", "plum"];
alert(fruits.length);	//3

요소 전체 출력하기

let fruits = ["apple", "orange", "plum"];
alert(fruits);	//apple, orange, plum

배열 요소의 자료형에는 제약이 없다

let arr = ["apple", {name : "hello"}, true, function(){alert("hello world");}];

//인덱스가 1인 요소(객체)의 name 프로퍼티를 출력
alert(arr[1].name);		//hello

//인덱스가 3인 요소(함수)를 실행
arr[3]();	//hello world

자료구조 (stack, queue)

Stack

한쪽 끝에서 요소를 더하거나 뺄 수 있게 해주는 자료구조. 후입선출(LIFO) - 가장 나중에 들어온 요소가 먼저 나간다.

  • push : 요소를 스택 끝에 넣기
  • pop : 스택 끝 요소를 제거하고, 제거한 요소 반환
let fruits = ["apple", "orange", "plum"];

//pop
alert(fruits.pop());	//배열에서 plum 제거하고 제거된 요소를 띄운다.
alert(fruits);		//apple, orange
//push
fruits.push("pear")
alert(fruits);		//apple, orange, pear

Queue

선입선출(FIFO) - 먼저 넣은 요소가 먼저 나온다.

  • push : 맨 끝에 요소 추가
  • shift : 제일 앞 요소를 꺼내 제거한 후 남아있는 요소들을 앞으로 밀어준다.
  • unshift : 배열 앞에 요소 추가
let fruits = ["apple", "orange", "plum"];

//shift
alert(fruits.shift());	//배열에서 apple 제거, 제거된 요소를 띄움
alert(fruits); 		//orange, plum

//unshift
fruits.unshift("apple");
alert(fruits); 		//apple, orange, plum

//push와 unshift는 요소 여러 개를 한 번에 더해줄 수 도 있다.
fruits= ["apple"];
fruits.push("orange", "pear");
fruits.unshift("pineapple", "lemon");
//["pineapple", "lemon", "apple", "orange", "pear"]
alert(fruits);

배열의 내부 동작 원리

배열은 특별한 종류의 객체이다. 대괄호를 사용해 접근하는 방식은 객체 문법에서 왔으며, 배열의 키가 숫자라는 점만 다르다. 숫자형 키를 사용하기 때문에 객체 기본 기능 이외에도 순서가 있는 컬렉션을 제어하게 해주는 특별한 메소드를 제공한다. 배열은 7가지 원시 자료형에 해당하지 않고, 객체형에 속하기 때문에 객체처럼 동작한다. 배열은 객체와 마찬가지로 참조를 통해 복사된다.

let fruits = ["banana"];
let arr = fruits;	//참조를 복사함(두 변수가 같은 객체를 참조)

alert(arr === fruits);	//true
arr.push("pear");	//참조를 이용해 배열을 수정
alert(fruits);	//banana, pear - 요소가 두 개가 된다.

자바스크립트 엔진은 배열의 요소를 인접한 메모리 공간에 차례로 저장해 연산 속도를 높인다. 그런데 개발자가 배열을 '순서가 있는 자료의 컬렉션'처럼 다루지 않고 일반 객체처럼 다루면 이런 기법이 제대로 동작하지 않는다.

let fruits = [];	//빈 배열 생성
fruits[99999] = 5;	//배열의 길이보다 훨씬 더 큰 숫자를 이용해 프로퍼티 생성
fruits.age = 25;	//임의의 이름을 사용해 프로퍼티를 생성

배열은 객체이므로 예시처럼 원하는 프로퍼티를 추가해도 문제가 발생하지는 않는다. 하지만 위와 같이 코드를 작성하면 자바스크립트 엔진이 배열을 일반 객체처럼 다루게 되어 배열을 다룰 때만 적용되는 최적화 기법이 동작하지 않아 배열 특유의 이점이 사라진다.

잘못된 방법의 예시

  • arr.test = 5 같이 숫자가 아닌 값을 프로퍼티 키로 사용하는 경우
  • arr[0]arr[1000]만 추가하고 그 사이에 아무런 요소도 없는 경우
  • arr[1000],arr[999] 같이 요소를 역순으로 채우는 경우

배열은 순서가 있는 자료를 저장하는 용도로 만들어진 특수한 자료구조이다. 배열 내장 메서드들도 이런 용도에 맞게 만들어졌기 때문에 배열을 사용할 땐 목적에 맞게 사용해야한다.

성능

pushpop은 빠르지만 shiftunshift는 느리다.

배열 앞에 무언가를 해주는 메서드가 배열 끝에 무언가를 해주는 메서드보다 느리다.
이유 : 나머지 요소의 인덱스를 모두 수정해야 하기 때문에.

  • push나 pop의 경우 : 기존 인덱스 유지
  • shift, unshift의 경우 : 요소 인덱스 수정, 나머지 인덱스 이동, length 프로퍼티 값 수정

반복문

for

인덱스를 사용하여 순회하는 방법

let arr = ["apple", "orange", "pear"];
for (let i=0; i<arr.length; i++){
  alert(arr[i]);
}

for .. of

let fruits = ["apple", "orange", "pear"];
for (let fruit of fruits){
  alert(fruit);
}

for .. of를 사용하면 현재 요소의 인덱스는 얻을 수 없고, 값만 얻을 수 있다.
for .. in은 배열에 절대 사용하지 않는다.

배열 함수

length 프로퍼티

length 프로퍼티 : 가장 큰 인덱스에 1을 더한 값
만약 배열에 요소가 하나가 있지만 인덱스가 아주 큰 경우 length도 커진다.

let fruits = [];
fruits[123] = 'apple';
alert(fruits.length);	//124

length의 값을 수동으로 증가시키면 아무 일도 일어나지 않지만 감소시키면 배열이 잘린다. 이러한 특징을 사용하면 arr.length = 0을 통해 배열을 비울 수 있다.

toString 메서드

배열엔 toString 메서드가 구현되어 있어 alert를 통해 호출하면 문자열이 반환된다.

let arr = [1, 2, 3];
alert(arr);	//1,2,3
alert([1,2]+1);	//1,21
alert("1,2"+1);	//1,21

기타

trailing 쉼표

배열의 마지막 요소를 객체와 마찬가지로 쉼표로 끝날 수 있다.

let fruits = [
  "apple",
  "orange",
  "plum",
];

위와 같이 쉼표를 사용하면 모든 줄의 생김새가 유사해지기 때문에 요소를 넣거나 빼기가 쉬워진다.

다차원 배열

행렬을 저장하는 용도로 사용할 수 있다.

let matrix = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9],
];
alert(matrix[1][1]);	//5

0개의 댓글