본문 바로가기
Research/Javascript

Javascript_for, for in, for of는 무엇이 다른가(번역)

by RIEM 2023. 2. 6.

들어가기

자바스크립트에서는 for문 뿐만 아니라 for..in, for..of 등 다양한 유형의 반복문들이 있다. 이들은 서로 어떤 점에서 다른지 알아보자.

목차

  1. 자바스크립트의 반복문의 유형과 특징
  2. 객체인 배열에 키/값 쌍을 추가하면 키는 어디에 있나?
  3. Non-numeric property가 포함된 배열에 반복문을 돌리면?
  4. 빈 공간(,,)이 포함된 배열에 반복문을 돌리면?
  5. 그 외
  6. 정리

6. 정리

numeric vs. non-numeric property 관점에서 반복문 비교

  • for : numeric property만 출력
  • for of : numeric property만 출력
  • forEach : numeric property만 출력
  • for in : numeric + non-numeric property 모두 출력

빈 공간['a', ,'b'] 관점에서 반복문 비교

  • 빈 공간(hole)을 무시하고 배열을 돌고 싶다면 -> for..in, forEach
  • 빈 공간(hole)까지 모두 파악하고 싶다면 -> for문, for of

1. 자바스크립트의 반복문의 유형과 특징

우선 자바스크립트에서 제공하는 반복문은 크게 3개가 있다.

  • for문
  • while문
  • do...while

하지만 이것 말고도 자바스크립트에서는 반복문의 기능을 수행하는 것들이 있다.

  • forEach : 배열 순회
  • for...in : 객체 프로퍼티 순회
  • for...of : 객체 값 순회

while을 제외한 반복문의 특징은 아래와 같다.
| 반복문 | 키로 접근 | 값으로 접근 |
| --------- | --------- | ----------- |
| for | O | X |
| for..in | O | X |
| for..of | X | O |
| forEach | O | O |

for, for..in은 요소 그 자체가 아니라 index를 기반으로 정보를 찾는다. 반면 for of는 요소로 접근할 수 있다.for Each는 요소, 인덱스 모두 접근할 수 있는데, 이는 forEach의 두번째 매개변수가 인덱스를 가르키기 때문이다.

2. 객체인 배열에 키/값 쌍을 추가하면 키는 어디에 있나?

const friends = ['Johan', 'David', 'Anna'];

friends.hello = 'hello';

이 배열에는 우리의 친구들의 이름이 나열되어있다. 자바스크립트에서 배열은 객체 타입이다. 객체는 키/값 쌍 구조로 이루어져있다. 그런데 위의 배열을 보면 키/값 쌍이 아니라 그냥 값만 나열된 것처럼 보인다. 배열에 요소들을 추가해서 그 내막을 살펴보자.

배열에 키/값 쌍을 추가한다면?

const friends = ['Johan', 'David', 'Anna'];
friends.hello = 'hello';

console.log(friends) // [ 'Johan', 'David', 'Anna', hello: 'hello' ]

배열을 출력해보니 4번째 요소에 키와 값이 key:value 형태로 들어간 것을 확인할 수 있다.

hello 키/값 쌍은 index ([3])로 접근할 수 있을까?

...
console.log(friends[2]); // Anna
console.log(friends[3]); // undefined
console.log(friends['hello']) // hello

마지막 요소에 인덱스로 접근해보고자 했지만 undefined가 반환되었다. 해당 요소에 접근하려면 'hello' 키로 접근해야 한다.

const friends = ['Johan', 'David', 'Anna'];
friends.hello = 'hello';

console.log(friends.length) // 3

배열의 length를 출력하면 3이 나온다. numeric property만 길이에 포함된 것을 알 수 있다.

3. Non-numeric property가 포함된 배열에 반복문을 돌리면?

위의 실험으로 보았을 때, 다른 배열들은 숫자를 키로 가지고 있는 반면 새로 추가한 프로퍼티는 숫자가 아닌 문자열('hello') 형태의 키/값을 가진다. 이를 반복문으로 접근하면 모두 출력이 가능할까?

// `for`문 - 출력 불가
for (let i = 0; i < friends.length; i++) {
  console.log(friends[i])
}

// Johan
// David
// Anna
// `for of`문 - 출력 불가
for (let el of friends) {
  console.log(el)
}

// Johan
// David
// Anna
// `forEach`문 - 출력 불가

friends.forEach(el => console.log(el));

// Johan
// David
// Anna
// `for in`문 - 출력 가능!!

for (let el in friends) {
  console.log(el)
}

// 0
// 1
// 2
// hello

for...in문은 non-numeric property까지 출력해버린다

정리하자면 이렇다.

  • for : numeric property만 출력
  • for of : numeric property만 출력
  • forEach : numeric property만 출력
  • for in : numeric + non-numeric property 모두 출력

참조한 블로그 글에서는 for..in문이 non-numeric property까지 출력하기 때문에 왠만하면 쓰지않는 것이 좋다고 이야기한다. 개발자에게 예상치 못한 결과는 곧 에러와 직결되기 때문이 아닐까.

4. 빈 공간(,,)이 포함된 배열에 반복문을 돌리면?

반복문마다 빈 값을 처리하는 방식도 다르다.

const friends = ['Johan', 'David', ,'Anna'];
console.log(friends); // [ 'Johan', 'David', <1 empty item>, 'Anna' ]
console.log(friends.length); // 4

의도적으로 빈 공간을 추가해주자. 값이 없는데 그 공간 자체는 카운팅이 된다. 이건 마치 물리적으로 존재하지 않지만 마음 속에는 친구가 존재한다고 믿는 우리 개발자들의 마음을 비유적으로 표현한 것이 아닐까.

빈 공간을 물리적으로 존재하지 않는 친구라고 가정했을 때 반복문으로 세어보자. 과연 어떤 반복문이 빈 공간을 친구로 인정해줄까.

// for문 - 마음속에만 존재하는 친구도 인정 O
for (let i = 0; i < friends.length; i++) {
  console.log(friends[i]);
}
// Johan
// David
// undefined
// Anna
// for of 문 - 마음속에만 존재하는 친구도 인정 O
for(let friend of friends) {
  console.log(friend)
}

// Johan
// David
// undefined
// Anna
// for in문 - 마음속에만 존재하는 친구 인정 안함 X
for (let friend in friends) {
  console.log(friend)
}
// 0
// 1
// 3
// forEach 문 - 마음속에만 존재하는 친구 인정 안함 X
friends.forEach(friend => console.log(friend));

// Johan
// David
// Anna
  • for 문, for of문 : 마음속에만 존재하는 친구, 즉 빈 공간도 인정해준다 😃
  • for in, forEach : 마음속에만 존재하는 친구, 즉 빈 공간 인정 안해준다 ❌

for..in, forEach는 마음속에만 존재하는 친구, 즉 빈 공간은 인정해주지 않기에 반복 시 카운팅하지 않는다. 사실, 인덱스로 접근하는 for in은 비록 인정해주지 않았지만 마지막 인덱스가 2가 아닌 3이라고 표현한 점을 보면 암묵적으로 친구를 인정해줌을 알 수 있다. 하지만 forEach는 피도 눈물도 없는 친구다. 하지만 현실은 냉혈한들이 필요할 때가 있다.

5. 그 외

더 자세히 알고싶다면 참조 블로그 글 내용을 참조하면 되겠다. Function context, Async/Await and Generators 관점에서 비교한 내용도 포함되어 있다.

주 내용은

  • 반복문 별로 화살표 함수와의 조합
  • 반복문 별로Async/Await와의 조합
    등이 있다.

6. 출처

댓글