[JavaScript] 배열(Array)과 이터러블(Iterable)
배열 (Array)
일반적인 자료구조에서의 배열은 '연속된 메모리 공간에 나열된 동일한 타입의 데이터(요소)들의 집합'을 이야기한다.
때문에 배열의 주소만 알고 있다면 해당 배열의 n번째 데이터는 어떤 값인지 O(1)의 속도로 (아주 빠르게) 알 수 있다.
자바스크립트의 배열은 이러한 배열의 특징을 흉내내고 있는 아주 특수한 객체다.
const arr = {
0: 100,
1: 123,
2: 129,
length: 3
}
// arr[0] === 100
// arr[1] === 123
// arr.length === 3
위와 같이 생긴 객체의 프로퍼티에 접근하는 것은 일반적인 배열을 사용법과 똑같다는 것을 알 수 있다.
위와 같이 자바스크립트에서의 배열은 index를 key로 프로퍼티 값에 접근할 수 있고, length라는 프로퍼티를 갖고 있는 특수한 객체라고 보면 된다.
객체의 특성을 갖는 자바스크립트에서의 배열은 일반적인 자료구조에서의 배열과 다른 특징을 갖고있다.
1. 자바스크립트의 배열은 다양한 타입의 프로퍼티를 가질 수 있다.
(일반 배열은 동일한 타입의 원소만 가질 수 있다)
2. 데이터 접근은 미세하게 더 느리지만 배열의 확장과 축소에 있어서는 더 빠르다.
(일반 배열은 데이터 접근이 더 빠르지만 배열의 길이를 늘리는데 많은 비용이 든다.)
유사배열객체
하지만 사실 index로된 프로퍼티 키들과 length만 있는 객체를 모두 배열이라고 볼 수는 없다.
이러한 객체는 유사배열객체라 불리고 배열과 두가지 차이점이 있다.
첫 번째로, 유사배열객체에서는 map, reduce, filter 같은 Array.prototype에 있는 빌트인 메소드가 없다.
두 번째로, 유사배열객체는 순회가능한 이터러블 객체가 아니다.
하지만 Array.from 이라는 메소드를 사용한다면 유사배열객체를 배열로 변환해 map 등의 메소드를 사용하거나 순회할 수 있다.
// 유사배열 객체
const notArr = {
0: 100,
1: 200,
length: 2
};
// 배열
const realArr = Array.from(notArr);
이터러블 (iterable)
이터러블은 '반복(순회) 가능 한' 이란 뜻이다.
자바스크립트에서 데이터들을 통일된 방법으로 순회 하기 위해 일정한 규약을 만들었는데, 이러한 규약을 이터레이션 프로토콜 이라고 한다. 그리고 이러한 규약을 따르는 객체들을 순회가능한 객체, 이터러블 객체라고 한다.
이터러블은 for ... of 문으로 순회할 수 있고, 전개연산자(Spread Operator)와 디스트럭처링 할당의 대상이 될 수 있으며,
대표적인 빌트인 이터러블로는 배열, 문자열, Set, Map 등이 있다.
이터레이션 프로토콜
객체는 [Symbol.iterator]를 키 값으로 하는 객체를 반드시 가져야한다. (이터러블 프로토콜)
해당 객체를 이터레이터 객체라고 하는데, 이터레이터 객체는 next라는 이름의 메소드를 갖고 있어야 한다.
next 메서드는 해당 메소드가 끝났는지의 유무를 담은 done 프로퍼티(boolean)과, 반복자로 부터 반환되는 value 값을 반환해야 한다. (이터레이터 프로토콜)
이터레이션 프로토콜 = 이터러블(iterable) 프로토콜 + 이터레이터(iterator) 프로토콜
이터러블은 아래와 같은 특징들을 가진다.
for ... of 문
이터러블 객체는 for ... of 문으로 순회가 가능해지면서 정확한 요소 탐색을 할 수 있다.
const fruits = ['🥝', '🥕', '🍎'];
// 🥝, 🥕, 🍎 가 순차적으로 console에 출력
for (const fruit of fruits) {
console.log(fruit);
}
// string도 이터러블
const name = 'hobin';
// h, o, b, i, n 이 순차적으로 console에 출력
for (const c of name) {
console.log(c);
}
전개 연산자 (Spread Operator)
전개 연산자란 이터러블 요소를 모두 빼 내 나열한다. 아래 예시를 보면 이해가 더 쉬울 것 같다.
function sum (a, b, c) {
return a + b + c;
}
const numbers = [1, 2, 3];
console.log(sum(...numbers)); // 1 + 2 + 3 = 6
이렇게 함수에 변수로 할당하는 방법 외에도 배열(객체)의 요소로 새로운 배열(객체)을 만들 때 자주 사용한다.
const arr1 = [1, 2, 3];
const arr2 = ['a', 'b', 'c'];
const newArr1 = arr1; // newArr1 === arr1
const newArr2 = [...arr1]; // newArr2 !== arr1
const newArr3 = [...arr1, ...arr2]; // [1, 2, 3, 'a', 'b', 'c']
디스트럭처링 할당 (Destructuring Assignment)
디스트럭처링 할당은 구조화된 배열 또는 객체를 Destructuring(비구조화, 파괴)하여 개별적인 변수에 할당하는 것이다.
배열 또는 객체 리터럴에서 필요한 값만을 추출하여 변수에 할당하거나 반환할 때 유용하다.
const arr = ['hov', '010-xxxx-xxxx'];
const [name, contact] = arr;
console.log(name); // hov
console.log(contact); // 010-xxxx-xxxx
객체는 동일한 프로퍼티 키 이름에 할당된다.
const obj = {
type: '🍓',
size: 'small',
...
}
const {type} = obj;
console.log(type); // 🍓
이번에 자바스크립트를 집중해서 공부하면서 배열에 대해서 확실하게 정리할 수 있었다.
직접 원하는 방향으로 이터러블 객체를 만들어 사용하는데에는 아직 시간이 조금 더 걸리겠지만 연습하고 어떻게 쓸 수 있는지 고민해보면 재미있는 기술이 될 것 같다 🙂