토막지식시리즈/javascript 토막지식
for of vs for
GrapeMilk
2024. 9. 9. 11:15
javaScript에서 for...of와 일반적인 for 루프의 성능 차이는 사용하는 용도에 따라 다르지만 보통 for의 성능이 좋다
1. for
- 동작 방식: for 루프는 인덱스를 기반으로 배열이나 반복 가능한 객체에 직접 접근한다.
- 성능: 배열의 길이가 크고 단순히 인덱스를 사용해 값을 순회할 때, 최적화가 잘 되어 있기 때문에 성능 면에서 이점이 있다.
const arr = [1, 2, 3, 4];
for (let i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
2. for...of
- 동작 방식: for...of는 반복 가능한 객체(iterable)에서 값 자체를 순회한다. 배열 외에도 Map, Set 같은 다른 이터러블 객체에도 사용할 수 있다.
- 성능: for...of는 내부적으로 이터레이터를 생성하고 그 값을 가져오기 때문에, 단순 배열 순회에 대해서는 for 루프보다 약간 느릴 수 있다. 하지만 코드의 가독성과 간결성 면에서는 장점이 있다.
const arr = [1, 2, 3, 4];
for (const value of arr) {
console.log(value);
}
성능 비교
- 작은 배열: 배열의 크기가 작을 경우 두 루프의 성능 차이는 미미합니다.
- 큰 배열: 큰 배열을 순회할 때는 for 루프가 성능 면에서 더 효율적일 수 있다. 특히 반복 횟수가 많을 때는 차이가 더 커진다.
- 가독성: 성능을 크게 고려하지 않는다면, 가독성 면에서 for...of가 더 직관적일 수 있다.
for...of가 성능이 느린 이유(이터레이터)
javaScript에서 for...of는 이터러블 객체를 순회할 때 이터레이터(iterator)를 사용한다. 이터레이터는 값을 순차적으로 접근할 수 있는 객체이며, for...of 루프는 이터레이터의 동작을 간결하게 해주는 문법이다.
1. 이터러블과 이터레이터
이터러블은 이터레이터를 반환할 수 있는 객체이다. Symbol.iterator 메서드를 가지며, 이 메서드는 이터레이터를 반환한다. 이터레이터는 next() 메서드를 통해 순차적으로 값을 반환하는 객체이다.
const arr = [1, 2, 3, 4];
// 이터레이터 생성
const iterator = arr[Symbol.iterator]();
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: 4, done: false }
console.log(iterator.next()); // { value: undefined, done: true }
- arr[Symbol.iterator]()를 호출하면 배열의 이터레이터가 반환된다.
- iterator.next()는 이터레이터를 통해 값을 하나씩 반환한다.
- next() 메서드는 { value, done } 객체를 반환하며, value는 다음 값이고 done은 이터레이션이 끝났는지 여부를 나타낸다.
2. for...of로 이터레이터 사용
for...of는 위와 같은 이터레이터 로직을 내부적으로 자동으로 처리해준다. 즉, 개발자가 직접 next() 메서드를 호출할 필요 없이 값만 쉽게 순회할 수 있다.
const arr = [1, 2, 3, 4];
for (const value of arr) {
console.log(value);
}
- 이 코드는 내부적으로 arr[Symbol.iterator]()를 호출하여 이터레이터를 생성하고, next()를 반복적으로 호출해 값을 순차적으로 가져온다.
- done이 true가 될 때까지 자동으로 순회가 이루어진다.
- 이 과정이 index로 단순히 값을 가져오는 for 보다 성능을 느리게 한다.
3. 이터레이터를 수동으로 사용한 for...of의 동작 원리
for...of가 내부적으로 하는 작업을 수동으로 구현한 코드
const arr = [1, 2, 3, 4];
// 이터레이터 생성
const iterator = arr[Symbol.iterator]();
let result = iterator.next();
while (!result.done) {
console.log(result.value);
result = iterator.next();
}
위 코드는 for...of와 동일한 결과를 얻을 수 있다. 직접 next()를 호출하고 이터레이션을 제어한다.