배열을 기준으로 예시를 들어보면 이러한 결과가 나온다.
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. 정리
- forEach는 Array를 순회하는 데 사용되는 Array의 메소드.
- for-in은 Object의 key를 순회하기 위해 사용되는 반복문. 단, 확장 속성까지 함께 순회한다는 점 고려. 일반객체O / 배열O(but X)
- 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 |
댓글