본문 바로가기
언어/Javascript, Typescript

[js] iterable 객체, Array.from

by minhyeok.lee 2023. 2. 18.
반응형

iterable(반복 가능한) 객체, Array.from 메소드

iterable(반복 가능한) 객체란?

1. 반복 가능한(iterable, 이터러블) 객체는 배열을 일반화한 객체이다.

2. for..of 반복문을 적용할 때 Symbol.iterator를 호출하는 데 iterable한 객체가 아니라면 에러가 발생한다.

 - Symbol.iterator는 반드시 이터레이터(iterator, 메소드 next가 있는 객체) 를 반환해야 한다.
 - for..of는 반환된 객체(이터레이터)만을 대상으로 동작한다.
 - for..of에 다음 값이 필요하면, for..of는 이터레이터의 next()메소드를 호출한다.
 - next()의 반환 값은 {done: Boolean, value: any}와 같은 형태이어야 한다.

 - done=true는 반복이 종료되었음을 의미한다.

 - done=false일땐 value에 다음 값이 저장된다.

3. 배열은 대표적인 이터러블이다.

4. 배열 외에도 다수의 내장 객체가 반복 가능하다. (문자열 등등)


for..of는 문자열의 각 글자를 순회한다. (문자열의 길이만큼 반복한다.)

for (let char of "abcdefg") {
  console.log( char );
}

 

출력값

a
b
c
d
e
f
g


서로게이트 쌍(surrogate pair)에도 잘 동작한다.

 * 서로게이트 쌍이란?

2023.02.17 - [개발 용어 정리] - Unicode(유니코드), UTF-8, UTF-16, Surrogate(서로게이트) 쌍

 

Unicode(유니코드), UTF-8, UTF-16, Surrogate(서로게이트) 쌍

Unicode(유니코드), UTF-8, UTF-16, Surrogate(서로게이트, 써로게이트) 쌍이란? 유니코드 (ISO-10646) 1. 흔히 Unicode라고 불리는 문자세트와 그 부호화에 대해서 정의하고 있는 표준이다. 2. 유니코드는 전 세

kfdd6630.tistory.com

let str = '𝒳😂';
for (let char of str) {
    console.log( char );
}

 

출력값

𝒳
😂

 

 


이터레이터를 명시적으로 호출하기

for..of를 사용했을 때와 동일한 방법으로 문자열을 순회할 때, 직접  iterator()객체를 직접 호출한다.

다음 코드는 문자열 이터레이터를 만들고, 여기서 값을 ‘수동으로’ 가져온다.

 

아래는 명시적으로 이터레이터를 호출하지 않은 코드이다.

let str = "Hello";
for (let char of str) console.log(char);

 

아래는 명시적으로 이터레이터를 호출한 코드이다.

let str = "Hello";

let iterator = str[Symbol.iterator]();

while (true) {
  let result = iterator.next();
  if (result.done) break;
  console.log(result.value);
}

 

출력값(위 두 코드는 동일하게 동작한다.)

H
e
l
l
o

이터레이터를 명시적으로 호출하는 경우는 거의 없다.

하지만 이 방법을 사용하면 for..of를 사용하는 것보다 반복 과정을 더 잘 통제할 수 있다는 장점이 있다.

반복을 시작했다가 잠시 멈춰 다른 작업을 하다가 다시 반복을 시작하는 것과 같이 반복 과정을 여러 개로 쪼개는 것이 가능하다.

이터러블과 유사 배열 (비슷해 보이지만 아주 다른 용어)

1. 
 - 이터러블(iterable)은 메소드 Symbol.iterator가 구현된 객체(for..of  사용가능)이다.
 - 유사 배열(array-like)은 인덱스와 length 프로퍼티가 있어서 배열처럼 보이는 객체이다.
 - 옛 레거시 코드에서 이터러블 객체나 유사 배열 객체 혹은 둘 다인 객체를 만날 수 있다.

 

2. 

 - 이터러블 객체라고 해서 유사 배열 객체는 아니다.

 - 유사 배열 객체라고 해서 이터러블 객체인 것도 아니다.
 - 이터러블 객체가 인덱스도 없고 length 프로퍼티도 없으므로 유사 배열 객체가 아니다.

 

3.
 - 이터러블 객체(for..of 를 사용할 수 있음)이면서 유사배열 객체(숫자 인덱스와 length 프로퍼티가 있음)인 문자열이 대표적인 예이다.

 


아래 예시의 객체는 유사 배열 객체이지만 이터러블 객체가 아니다.

let arrayLike = { // 인덱스와 length프로퍼티가 있음 => 유사 배열
  0: "Hello",
  1: "World",
  length: 2
};

// Symbol.iterator가 없으므로 에러 발생
for (let item of arrayLike) {}

 

출력값

TypeError: arrayLike is not iterable

 


Array.from 메소드란?

이터러블과 유사 배열은 대개 배열이 아니기 때문에 push, pop 등의 메소드를 지원하지 않는다.

때문에 이터러블과 유사 배열을 배열처럼 다루고 싶을 때 Array.from 메소드를 사용하면 된다.


범용 메소드 Array.from는 이터러블이나 유사 배열을 받아 진짜 Array를 만들어준다.

이 과정을 거치면 이터러블이나 유사 배열에 배열 메소드를 사용할 수 있다.

let arrayLike = {
  0: "Hello",
  1: "World",
  length: 2
};

let arr = Array.from(arrayLike);
alert(arr.pop());

L7에 Array.from은 객체를 받아 이터러블이나 유사 배열인지 확인한다. 넘겨 받은 인수가 이터러블이나 유사 배열인 경우, 새로운 배열을 만들고 객체의 모든 요소를 새롭게 만든 배열로 복사한다.

 

출력값

World

 


아래Array.from를 사용해 문자열을 배열로 만든 예제 코드

let str = '𝒳😂';

let chars = Array.from(str);

console.log(chars);

str를 분해해 글자가 담긴 배열로 만들었다.

 

위 예시는 기술적으로 아래 예시와 동일하게 동작한다.

let str = '𝒳😂';

let chars = []; // Array.from 내부에선 아래와 동일한 반복문이 돌아간다.
for (let char of str) {
  chars.push(char);
}

console.log(chars);

Array.from은 str.split과 달리, 문자열 자체가 가진 이터러블 속성을 이용해 동작한다.

따라서 for..of처럼 서로게이트 쌍에도 제대로 적용된다.

 

출력값

[ '𝒳', '😂' ]

결론:  Array.from을 사용한 예시가 더 짧은걸 볼 수 있다.



Array.from을 사용하면 서로게이트 쌍을 처리할 수 있는 slice를 직접 구현할 수 있다.

let str = '𝒳😂𩷶';

// 내장 순수 메소드는 서로게이트 쌍을 지원하지 않는다.
console.log( str.slice(1, 3) ); // 쓰레깃값 출력 (영역이 다른 특수 값)


function slice(str, start, end) {
  return Array.from(str).slice(start, end).join('');
}


console.log( slice(str, 1, 3) ); // 출력값: 😂𩷶

 

출력값

��
😂𩷶

 

요약
1. for..of을 사용할 수 있는 객체를 이터러블이라고 부른다.
2. 이터러블엔 메소드 Symbol.iterator가 반드시 구현되어 있어야 한다.
3. obj[Symbol.iterator]의 결과는 이터레이터라고 부른다.

4. 이터레이터는 이어지는 반복 과정을 처리한다.
5. 이터레이터엔 객체 {done: Boolean, value: any}을 반환하는 메소드 next()가 반드시 구현되어 있어야 한다.

6. 여기서 done:true은 반복이 끝났음을 의미하고 그렇지 않은 경우엔 value가 다음 값이 된다.
7. 메소드 Symbol.iterator는 for..of에 의해 자동으로 호출되는데, 개발자가 명시적으로 호출하는 것도 가능하다.
8. 문자열이나 배열 같은 내장 이터러블에도 Symbol.iterator가 구현되어 있다.
9. 문자열 이터레이터는 서로게이트 쌍을 지원한다.
10. 인덱스와 length 프로퍼티가 있는 객체는 유사 배열이라 불린다.

11. 유사 배열 객체엔 다양한 프로퍼티와 메소드가 있을 수 있는데 배열 내장 메소드는 없다. 
12 .대부분의 메소드는 진짜 배열이 아닌 이터러블이나 유사 배열을 대상으로 동작한다고 쓰여 있는걸 볼 수 있다. 이 방법이 더 추상적이기 때문이다.

 

* 배열과 문자열은 이터러블 객체이기때문에 for..of을 사용할 수 있다.

* 객체는 인덱스와 length 속성이 있더라도 for..of를 사용할 수 없기때문에 array.from으로 배열을 만들어주거나 객체를 위한 반복문인 for..in을 사용하자.

반응형

댓글