for-of문
for(let value of myArray){
console.log(value);
}
for-in
문이 객체의 속성들을 순회하기 위한 구문이라면, for-of
문은 배열의 요소들, 즉 data 를 순회하기 위한 구문이다. 정확히는 일반 Object
요소를 제외한 Array
, Map
, Set
등의 객체 타입을 순회할 수 있다. (추가로 String
도 가능하다. 문자열로 이루어진 배열로 보기 때문)
forEach
와는 다르게 break
, continue
, 그리고 return
구문과 함께 사용할 수 있다.
for-of
문은 어떤 메소드를 반복 호출하는 방식으로 동작한다. Array
, Map
, Set
등의 객체들은 공통적으로 이터레이터(iterator) 메소드를 제공한다. 일반 객체는 이터레이터 메소드를 제공하지 않기 때문에 for-of
문으로 순회가 불가능하다.
Array
의 속성을 살펴보면 Symbol.iterator
가 포함되어있다.
반면 일반 Object
에는 존재하지 않는다.
Array
와 같이 이터레이터 메소드를 제공하여 for-of
문으로 순회 가능한 객체를 '이터러블(Iterable)' 이라 한다.
Iterable의 정의
이터러블의 정의는 다음과 같다.
Symbol.iterator 메소드를 구현하거나 프로토타입 체인에 의해 상속한 객체로, for-of 문에서 순회할 수 있으며 Spread 문법의 대상으로 사용할 수 있다.
일반 객체도 간단하게 이터러블로 만들 수 있다.
객체 안에 [Symbol.iterator]()
를 구현하면 된다. 이렇게 구현된 이터러블을 커스텀 이터러블이라 한다.
당신이 어떤 객체에든 myObject.toString() 메소드를 추가하면 JS가 이를 통해 해당 객체를 문자열로 변환하는 방법을 알아내는 것과 마찬가지로, 어떤 객체에든 [Symbol.iterator]메소드를 추가하면 JS는 해당 객체를 어떻게 순회(loop)해야 하는지 알아낸다.
💡 .iterator()
가 아닌 [Symbol.iterator]
메소드를 사용하는 이유는 무엇인가
기존에 작선된 코드에서 어떤 객체가 이미 .iterator()
라는 메소드를 갖고 있다면 문제가 생긴다. 그래서 iterator
라는 평범한 문자열 이름 대신 Symbol
을 사용한 고유한(어떤 코드와도 충돌하지 않는) 메소드를 정의해준 것이다.
Symbol.iterator()
[Symbol.iterator]()
는 새로운 이터레이터 객체를 반환한다.
이터레이터 객체란 next()
메소드를 가진 객체를 말한다.
이 next()
메소드는 이터러블의 각 요소를 순회하기 위한 포인터의 역할을 하며, 호출시마다 value
와 done
속성을 가진 이터레이터 result
객체를 반환한다.
value
는 현재 순회중인 이터러블의 값을 반환하고,done
은 이터러블의 순회 완료 여부를 반환한다.
for-of
문은 [Symbol.iterator]()
메소드의 호출로 시작하여 next()
를 반복적으로 호출하며 객체를 순회한다. 순회하면서 next()
가 반환한 이터레이터 result
객체의 value
프로퍼티 값을 for-of
문의 변수에 할당한다.
// 배열은 이터러블이다.
const array = [1, 2, 3];
// 이터러블은 Symbol.iterator 메소드를 소유한다.
// Symbol.iterator 메소드는 이터레이터를 반환한다.
let iter = array[Symbol.iterator]();
// 이터레이터는 next 메소드를 소유한다.
// next 메소드는 이터레이터 result 객체를 반환한다.
console.log(iter.next()); // {value: 1, done: false}
console.log(iter.next()); // {value: 2, done: false}
console.log(iter.next()); // {value: 3, done: false}
console.log(iter.next()); // {value: undefined, done: true}
위의 코드에서 보면, next()
를 호출할 때 마다 요소를 하나씩 순회하며, 순회가 끝났을 때는 done: true
를 반환한다.
📌
http://hacks.mozilla.or.kr/2015/08/es6-in-depth-iterators-and-the-for-of-loop/