JavaScript 실용적인 for 사용법

2023년 08월 15일

어떤 for를 써야할까

JavaScript에는 여러 종류의 for loop이 있다. 하는 일은 크게 달라보이지 않아서 forEach, for of, for in, for 중 어떤 함수가 쓰기에 적절한지 판단하기 어려웠다. 그래서 상황별로 어떤 for loop이 맞을지 한번 정리.

기준

코딩할 때 고민 할 만한 몇가지 기준으로 for loop을 나눠볼 수 있다.

  1. for 안에서 손쉽게 index 사용이 가능한지
  2. 비동기 처리 작업시 순차적으로 iteration이 작동하는지
  3. 중간에 break가 가능한지
  4. 성능적인 부분까지

1. for

전통적인(?) for loop이다. 문법 형태도 굉장히 직관적이다.

for (let i = 0; i < array.length; i++) {
}

index 사용

index를 기준으로 iterator를 만들면 쉽게 사용이 가능하다.

const fruits = ["딸기", "바나나", "망고"];

for (let i = 0; i < fruits.length; i++) {
  console.log(`Index: ${i}, Value: ${fruits[i]}`);
}

비동기

loop 안에서 비동기 작업 수행을 위해 async/await 를 사용하여 코드를 작성할 수 있다.

순차적으로 loop을 돌며 실행된다.

const makeIceCream = (fruit) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(`: 🍦 ${fruit}맛 아이스크림`);
    }, 1000);
  });
};

const fruits = ["딸기", "바나나", "망고"];

(async () => {
  for (let i = 0; i < fruits.length; i++) {
    console.log(`${fruits[i]}맛 아이스크림 나갑니다`);
    const iceCream = await makeIceCream(fruits[i]);
    console.log(iceCream);
  }
})();

//로그 결과
딸기맛 아이스크림 나갑니다
: 🍦 딸기맛 아이스크림
바나나맛 아이스크림 나갑니다
: 🍦 바나나맛 아이스크림
망고맛 아이스크림 나갑니다
: 🍦 망고맛 아이스크림

break

조건에 맞게 루프를 중지할 수 있다.

2. forEach

forEach는 다른 for와 좀 다르다. 가장 주의해서 봐야할 메서드

index 사용

forEach는 굉장히 편리하게 value, index를 사용할 수 있다. index는 두번째 파라미터로 사용 가능하다.

const fruits = ["딸기", "바나나", "망고"];
fruits.forEach((value, index) => {
	 console.log(`Index: ${index}, Value: ${value}`);
}

비동기 지원 X

아래 코드를 실행해보면 forEach안에서 await은 예상과 다르게 작동한다. forEach는 콜백 함수 안에 await을 게의치 않고 코드를 실행한다.

그렇기에 비동기코드가 순차적으로 실행되길 원한다면 forEach 말고 다른 for를 사용하자.

const makeIceCream = (fruit) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(`: 🍦 ${fruit}맛 아이스크림`);
    }, 1000);
  });
};

const fruits = ["딸기", "바나나", "망고"];

fruits.forEach(async (fruit) => {
  console.log(`${fruit}맛 아이스크림 나갑니다`);
  const iceCream = await makeIceCream(fruit);
  console.log(iceCream);
});

//로그 결과
딸기맛 아이스크림 나갑니다
바나나맛 아이스크림 나갑니다
망고맛 아이스크림 나갑니다
: 🍦 딸기맛 아이스크림
: 🍦 바나나맛 아이스크림
: 🍦 망고맛 아이스크림

break

forEach loop내에서 break로 루프를 중지 할 수 없다. 위에 비동기 처리에서 알 수 있듯이 forEach는 순차적으로 진행되지 않기 때문에.

3. for in

index 사용

index 사용이 가능하다.

for in은 index를 기준으로 iteration을 한다.

const fruits = ["딸기", "바나나", "망고"];

for(const index in fruits){
	console.log(`Index: ${index}, Value: ${array[index]}`);
}

비동기 지원

loop 안에서 비동기 작업 수행을 위해 async/await 를 사용하여 코드를 작성할 수 있다.

(async () => {
  for (const i in fruits) {
    console.log(`${fruits[i]}맛 아이스크림 나갑니다`);
    const iceCream = await makeIceCream(fruits[i]);
    console.log(iceCream);
  }
})();

break

조건에 맞게 루프를 중지할 수 있다.

4. for of

index 사용

index를 어찌어찌 꺼내서 사용할 수는 있지만 for of 자체로는 지원하지 않는다.

for of는 element를 기준으로 iteration을 한다

const fruits = ["딸기", "바나나", "망고"];

for(const element of fruits) {
	console.log(element)
}

비동기 지원

loop 안에서 비동기 작업 수행을 위해 async/await 를 사용하여 코드를 작성할 수 있다.

(async () => {
  for (const fruit of fruits) {
    console.log(`${fruit}맛 아이스크림 나갑니다`);
    const iceCream = await makeIceCream(fruit);
    console.log(iceCream);
  }
})();

**for await of**은 또 뭐야?

interation을 돌고자하는 array가 promise일 때 사용하는 것. for loop 안에서 동작하는 async/await와는 관련이 없다.

하지만 보통은 사용하지 않는다. 보통 순환하려는 array는 이미 다 resolve 된 이후에 for loop을 쓰니까.

break

조건에 맞게 루프를 중지할 수 있다.

성능

각각 for 마다 실행 시간이 좀 다르다.

const array = Array(1000000);

console.time("for");
for (let i = 0; i < array.length; i++) {}
console.timeEnd("for");

console.time("forEach");
array.forEach((_, index) => {});
console.timeEnd("forEach");

console.time("for of");
for (const _ of array) {
}
console.timeEnd("for of");

console.time("for in");
for (const _ in array) {
}
console.timeEnd("for in");


//로그
for: 2.253ms
forEach: 1.738ms
for of: 17.164ms
for in: 2.217ms

나머지와 다르게 for of가 특히 느리다. 6~10배 정도 더 느리게 작동한다.

하지만 iteration횟수가 적다면 크게 고려하지 않아도 될 듯하다. 상대적으로 느리지만 ms단위의 사소한 차이다.

참고


TAGS
JAVASCRIPT