본문 바로가기
JavaScript

forEach / for-in / for-of 차이점

by whoyoung90 2022. 1. 31.
반응형

배열을 기준으로 예시를 들어보면 이러한 결과가 나온다.

const array = ['가', '나', '다', '라'];

array.forEach(el => {
  console.log(el);           // el은 배열의 요소값 👉 '가' '나' '다' '라'
})
for (let value of array) {
  console.log(value);        // value는 배열의 요소값 👉 '가' '나' '다' '라'
}
for (let key in array) {
  console.log(key);          // key는 배열의 인덱스값... 👉 '0' '1' '2' '3'
}

1.  for (배열의 길이만큼 순회)

초기값부터 시작해서 조건에 부합하면 계속 순회.

중간에 break문을 만나면 반복문을 중단.

 

2.  forEach (배열을 순회)

배열 메소드. 배열의 각 요소에 대해 callback을 실행

배열을 순회하므로 break 문을 사용할 수 없다. (이런 경우라면 for 문 사용)

가장 중요한 차이점은 forEach는 ES6 문법으로 콜백함수를 뿌린다는 점이다.

> for / forEach 차이점?
결과물은 똑같이 나오는 것으로 보일 수 있지만,  동기(sync)와 비동기(async)의 차이가 있다.

가령 for문을 썼던 곳에서는 오류가 나면 그 밑에 script단은 실행되지 않는다.
그래서 만약에 for문 뒤에 중요한 다른 이벤트나 커맨드는 안 읽어버리고 멈춰버린다.

async 방식의 forEach를 쓴다면 forEach 안에 오류가 있더라도 다른 이벤트나 커맨드는 뒤에 읽을 것이다.
그러나 본인이 원하지 않는 순서에 실행될 수 있다.

3.  map (배열을 순회)

배열 메소드. 배열의 각 요소에 대해 callback을 실행

배열을 순회하므로 중간에 break 문을 사용할 수 없다. (이런 경우라면 for문 사용)

forEach( )와 달리 실행결과를 모은 새 배열을 리턴 ( return 반드시 필요 )

const animals = ["dog", "cat"];

animals.forEach(el => {
  console.log(el);         // 'dog' 'cat'
});

let foo = animals.map(el => {
  console.log(el);         // 'dog' 'cat'
  return el;
});
console.log(foo);       // [ 'dog', 'cat' ]


/* 
 단순 반복이라면 for
 배열을 순회하려면 forEach
 배열을 순회 후 새 배열을 얻고 싶다면 map
*/

4.  for-in (object의 key 순회)

Object의 enumerable한 key에 차례로 접근하는데 사용되는 반복문.

 

for-in은 열거 가능한 값이 true로 설정되어 있어 key만 반복할 수있고

nonEnumerable(비열거형)인 value에는 접근할 수 없다.

 

Array에도 사용할 수 있지만 일반적으로 Object 를 제외한 객체에는 사용하지 않는 것이 좋다.

4-1.  해당 object의 요소뿐 아니라 prototype chain으로부터 상속받은 속성들도 함께 순회하기 때문!

Object.prototype은 프로토타입 체이닝의 "최상단"이므로 모든 데이터 타입에서 참조하여 사용 가능!

let obj = {
  name: 'woo young',
  age: 33,
  job: 'developer'
}
Object.prototype.foo = function() {
  return '😡';
}

for (let keys in obj) {
  console.log(keys);     // 'name' 'age' 'job' 'foo'
}

객체의 key를 keys로 받아 보고 싶었는데  Object의 prototype으로 만들어 둔 foo 함수까지 함께 순회하는 모습을 볼 수 있다.

 

이러한 이유 때문에 for in은 Object key를 순회하기 위해 불가피하게 사용하는 것이 아니라면 사용하지 않는 것이 좋다.

4-2.  Array에 사용하면 특정 순서에 따라 인덱스를 반환하지 않을 수 있기 때문!

mdn에서는 index 순서가 중요한 배열을 순회할때는 사용되지 않아야 한다고 명시되어있다.

 

참고) 배열 index는 enumerable한 정수로 된 열거 가능한 속성인데 반해
for-in 문은 정수가 아닌 이름을 가진 속성, 상속된 모든 열거 가능한 속성들을 순회하여 반환하기 때문이기도 하고,
앞서본 prototype chain도 같이 순회할 수 있기 때문이다.

 

간단히 말해,

for–in 문은 일반 Object의 문자열 키(key)를 순회하기 위해 만들어진 문법이므로 Array를 다루는데는 유용하지 않다!

이 와 같은 이유로 Array인 경우 for나 forEach, for-of 사용을 권장하고 있다.

 

> 그렇다면 왜 for-in 문을 쓸까?
for-in은 다른 반복문으로 충분히 대체 가능한데 왜 쓰는 것일까?
키-값 쌍이 선호되는 데이터의 경우나 특정 값을 가진 key가 있는지 확인하려는 경우에는 for-in이 유용하다.
객체에 key를 가져와서 어떤 작업을 처리하는 경우에는 for-in을 쓰기 편하다고 한다.

5.  for of (iterable-object의 value 순회) (일반 객체 불가)

forEach문과 달리 break, continue, return 구문과 함께 사용할 수 있다.

 

iterable한 객체(Array, Map, Set, String, TypedArray, arguments 등)에 대해 속성값(value)을 반복 순회한다.

일반 객체는 iterable하지 않기 때문에 for of를 사용하게 되면 타입에러가 뜬다.

/* 일반 객체는 타입에러 */
let obj = {
  name: 'woo young',
  age: 33,
  job: 'developer'
}
for (let value of obj) {
  console.log(value);     // TypeError: obj is not iterable
}


/* 속성값(value)를 순회 */
let arr = ['wooyoung', 33, 'developer'];
for (let value of arr) {
  console.log(value);     // 'wooyoung' 33 'developer'
}

6.   정리

  1. forEach는 Array를 순회하는 데 사용되는 Array의 메소드.
  2. for-in은 Object의 key를 순회하기 위해 사용되는 반복문. 단, 확장 속성까지 함께 순회한다는 점 고려. 일반객체O / 배열O(but X)
  3. for-of는 이터러블한 객체를 모두 순회(value 순회)할 수 있는 강력한 반복문! 일반객체X / 배열 O
반응형

'JavaScript' 카테고리의 다른 글

클로저 (Closure)  (0) 2022.03.30
콜백 함수도 함수로서 호출이다  (1) 2022.02.26
유사배열객체에 배열메서드 적용(call, apply)  (0) 2022.01.30
This에 대한 정리  (0) 2022.01.22
continue 문  (0) 2022.01.05

댓글