배열
- 순서가 있는 컬렉션을 저장할 때 쓰는 자료구조
배열 선언
let arr = new Array();
let arr = [];
각 배열 요소에는 0부터 시작하는 숫자(인덱스) 가 매겨져 있다. 이 숫자는 순서를 나타낸다.
배열 내 특정요소를 얻고싶다면 대괄호 안에 순서를 나타내는 순자인 인덱스를 넣어주면 된다.
let fruits = ["사과", "오렌지", "자두"];
alert( fruits[0] ); // 사과
alert( fruits[1] ); // 오렌지
alert( fruits[2] ); // 자두
# 자바스크립트의 배열은 Java의 배열과 다르게 크기를 미리 정하지 않는다(배열의 크기는 동적으로 변경이 가능하다.
배열 내부의 데이터 타입이 서로 다를 수 있다.(자료형의 제약이 없다.
// 요소에 여러 가지 자료형이 섞여 있습니다.
let arr = [ '사과', { name: '이보라' }, true, function() { alert('안녕하세요.'); } ];
// 인덱스가 1인 요소(객체)의 name 프로퍼티를 출력합니다.
alert( arr[1].name ); // 이보라
// 인덱스가 3인 요소(함수)를 실행합니다.
arr[3](); // 안녕하세요.
#trailing 쉼표
배열의 마지막 요소는 객체와 마찬가지로 쉼표로 끝날 수 있다.
let fruits = [
"사과",
"오렌지",
"자두",
];
pop,push와 shift-unshift
큐(queue)는 배열을 사용해 만들 수 있는 대표적인 자료구조로, 배열과 마찬가지로 순서가 있는 컬렉션을 저장하는데 사용한다.
큐에서 사용하는 연산
큐 - 선입선출(First-In-First-Out, FIFO)
push - 맨 끝에 요소를 추가한다.
shift - 제일 앞 요소를 꺼내 제거한 후 남아있는 요소들을 앞으로 밀어준다.
배열에는 두 연산을 가능하게 해주는 내장 메서드 push와 pop이 있다.
배열은 큐 이외 스택(stack)을 구현할 때도 쓰인다.
스택에서 사용하는 연산
스택 - 후입선출(Last-In-First-Out, LIFO)
push - 요소를 끝에 집어넣는다.
pop - 스택 끝 요소를 추출한다.
+ unshift : 배열 앞에 요소를 추가한다.
처음이나 끝에 요소를 더하거나 빼주는 연산을 제공하는 자료구조를 데큐 라고 부른다.
배열의 내부 동작 원리
배열은 특별한 종류의 객체이다.arr[0] 처럼 대괄호를 사용해 접근하는 방식은 객체 문법에서 왔다.
다만 배열은 키가 숫자라는 점만 다르다.
배열은 객체와 마찬가지로 참조를 통해 복사된다.
let fruits = ["바나나"]
let arr = fruits; // 참조를 복사함(두 변수가 같은 객체를 참조)
alert( arr === fruits ); // true
arr.push("배"); // 참조를 이용해 배열을 수정합니다.
alert( fruits ); // 바나나,배 - 요소가 두 개가 되었습니다.
자바스크립트 엔진은 배열의 요소를 메모리공간에 차례로 저장하여 연산 속도를 높힌다.
하지만 개발자가 배열을 일반 객체처럼 다루게되면 이런 기법들이 제대로 동작하지 않는다.
let fruits = []; // 빈 배열을 하나 만듭니다.
fruits[99999] = 5; // 배열의 길이보다 훨씬 큰 숫자를 사용해 프로퍼티를 만듭니다.
fruits.age = 25; // 임의의 이름을 사용해 프로퍼티를 만듭니다.
배열은 객체이기 때문에 프로퍼티를 추가해도 문제가 발생하지 않는다.
하지만 이렇게 코드를 작성하면 잡자스크립트 엔진이 배열을 일반 객체처럼 다루게 되어 배열을 다룰 때만 적용되는 최적화 기법이 동작하지 않아 배열 특유의 이점이 사라진다.
잘못된 방법의 예
- arr.test = 5 : 숫자가 아닌 값을 프로퍼티 키로 사용하는 경우
- arr[0] 과 arr[1000] 만 추가하고 그 사이에 아무런 요소도 없는 경우
- arr[1000],arr[999] 같이 요소를 역순으로 채우는 경우
배열은 순서가 있는 자료를 저장하는 용도로 만들어진 특수한 자료구조 이다.
배열 내장 메서드들은 이런 용도에 맞게 만들어졌다.
자바스크립트 엔진은 이런 특성을 고려하여 배열을 신중하게 조정하고 처리하므로 배열을 사용할 땐 목적에 맞게 사용해야한다.
임의의 키를 사용해야 한다면 배열보다는 일반 객체 {} 가 적합한 자료구조일 확률이 높다.
성능
push와 pop은 빠르지만 shift와 unshift는 느리다.
fruits.shift(); // 배열 맨 앞의 요소를 빼줍니다.
shift 메서드를 호출한 것과 동일한 효과는 보려면 3가지 동작을 모두 수행하야한다.
1. 인덱스가 0인 요소를 제거
2. 모든 요소를 왼쪽으로 이동 (1은0, 2는1)
3. length 프로퍼티 값을 갱신
그렇게되면 배열에 요소가 많으면 요소가 이동하는데 걸리는 시간이 길도 메모리 관련 연산도 많아진다.
unshift도 마찬가지 이다.
push,pop
push나 pop은 그렇지 않다
pop은 끝에 요소를 제거하고 length 프로퍼티의 값을 줄이면 된다.
pop 메서드는 요소를 옮기지 않으므로 각요소는 기존 인덱스를 그대로 유지한다.
push도 마찬가지이다.
반복문
for문은 배열을 순회할 때 쓰는 가장 오레된 방법이다.
let arr = ["사과", "오렌지", "배"];
for (let i = 0; i < arr.length; i++) {
alert( arr[i] );
}
다른방법으로는 for...of가 있다.
let fruits = ["사과", "오렌지", "자두"];
// 배열 요소를 대상으로 반복 작업을 수행합니다.
for (let fruit of fruits) {
alert( fruit );
}
for..of 를 사용하면 현재 요소의 인덱스는 얻을 수 없고 값만 얻을 수 있다.
배열은 객체형에 속하므로 for...in을 사용하는 것도 가능하다.
let arr = ["사과", "오렌지", "배"];
for (let key in arr) {
alert( arr[key] ); // 사과, 오렌지, 배
}
하지만 for..in은 모든 프로퍼티를 대상으로 순회한다.( 키가 숫자가 아닌 프로퍼티도 포함)
-> 키가 숫자형이 아닌 프로퍼티와 메서드가 문제를 일으킬 가능성이 있다.
배열에는 for..in은 삼가해야 한다.
length 프로퍼티
배열에 무언가 조작을 가하면 length 프로퍼티가 자동으로 갱신된다.
length프로퍼티는 배열내 요소의 개수가 아니라 가장 큰 인덱스에 1을 더한 값
length프로퍼티는 쓰기가 가능하다.
-> length의 값을 수동으로 증가시키면 아무 일도 일어나지 않는다.
하지만 값을 감소시키면 배열이 잘린다.
let arr = [1, 2, 3, 4, 5];
arr.length = 2; // 요소 2개만 남기고 잘라봅시다.
alert( arr ); // [1, 2]
arr.length = 5; // 본래 길이로 되돌려 봅시다.
alert( arr[3] ); // undefined: 삭제된 기존 요소들이 복구되지 않습니다.
이런 특징을 이용하여 arr.length = 0 을 사용하여 간단하게 배열을 비울 수 있다.
new Array()
new Array()를 이용해서도 배열을 만들 수 있다.
let arr = new Array("사과", "배", "기타");
숫자형 인수하나를 넣어서 new Array()를 호출하면 배열이 만들어지는데
이 배열에는 요소가 없는 반면 길이는 인수와 같아진다.
let arr = new Array(2); // 이렇게 하면 배열 [2]가 만들어질까요?
alert( arr[0] ); // undefined가 출력됩니다. 요소가 하나도 없는 배열이 만들어졌네요.
alert( arr.length ); // 길이는 2입니다.
다차원 배열
배열 역시 배열의 요소가 될 수 있다. 이런 배열을 가리켜 다차원 배열 이라고 부른다.
(다차원 배열은 행렬은 저장하는 용도로 사용)
let matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
];
alert( matrix[1][1] ); // 5, 중심에 있는 요소
toString
배열에는 toString 메서드가 구현되어 있어 모든 요소를 쉼표로 구분한 문자열이 반환된다.
let arr = [1, 2, 3];
alert( arr ); // 1,2,3
alert( String(arr) === '1,2,3' ); // true
배열에는 Symbol.toPrimitive나 valufOf 메서드가 없다.
문자열로 형변환이 일어나는 []는 빈문자열, [1]는 문자열 "1", [1,2]는 문자열 "1,2"로 변환된다
이항 덧셈연산자 "+"는 피연산자중 하나가 문자열인 겅우 나머지 피연산자도 문자열로 변환한다.
alert( "" + 1 ); // "1"
alert( "1" + 1 ); // "11"
alert( "1,2" + 1 ); // "1,21"
'자바 스크립트' 카테고리의 다른 글
JSON과 메서드 (0) | 2020.12.14 |
---|---|
자바스크립트 iterable (0) | 2020.12.14 |
자바스크립트 문자열 (0) | 2020.12.12 |
자바스크립트 숫자형 (0) | 2020.12.11 |
자바스크립트 원시값의 메서드 (1) | 2020.12.08 |
댓글