for ... of
for (변수선언문 of 이터러블) { ... }
- 이터러블을 순회하면서 이터러블의 요소를 변수에 할당한다.
- 내부적으로 Iterator의 next 메서드를 호출해 이터러블을 순회하며 next 메서드가 반환한 리절트 객체의 value 프로퍼티 값을 for ... of문의 변수에 할당한다.
for ... in
for (변수선언문 in 객체) { ... }
- 객체의 모든 프로퍼티를 순회하며 열거한다.
- 순회 대상 객체의 프로퍼티뿐만 아니라 상속받은 프로토타입의 프로퍼티까지 열거한다.
- Symbol을 키로한 프로퍼티는 열거하지 않는다.
- 객체의 프로토타입 체인 상에 존재하는 모든 프로토타입의 프로퍼티 중에서 프로퍼티 어트리뷰트 [[Enumerable]]의 값이 true인 프로퍼티를 순회하며 열거한다.
- ❗️이 부분은 프로토타입에 대해 더욱 상세히 하고 볼 것.
결국 한 문장으로 줄이면 for ... of는 배열 값 순환, for ... in은 객체 값 순환이다.
여기서 내가 궁금했던 점은 배열도 결국 객체인데, 왜 구분해서 사용하는가? 이다.
for ... of와 for ... in의 차이
The main difference between them is in what they iterate over.
-출처 : MDN web docs
앞서 보았듯 두개의 차이는 어떤 것을 반복하느냐이다.
1. 순서 보장의 차이
for ... of는 배열을 순차적으로 순회하기 때문에 순서가 유지되지만
for ... in은 순서를 보장하지 않는다.
const obj = {
2: 2,
3: 3,
1: 1,
b: 'b',
a: 'a'
};
for(const key in obj){
if(!obj.hasOwnProperty(key)) continue;
console.log(key + ': ' + obj[key]);
}
/*
1: 1
2: 2
3: 3
b: b
a: a
*/
이렇게 보면 순서를 잘 보장해주는 것 같긴 하지만 (브라우저에서 정렬을 해줌)
MDN에서 설명하는 예시를 보면
Object.prototype.objCustom = function () {};
Array.prototype.arrCustom = function () {};
const iterable = [3, 5, 7];
iterable.foo = "hello";
for (const i in iterable) {
console.log(i);
}
// "0", "1", "2", "foo", "arrCustom", "objCustom"
arrCustom이 먼저 출력되는 것을 볼 수 있다.
그래서 배열을 순회할 때는 for ... of문이나 forEach문을 권장한다.
2. for ... of 으로 객체를, for ... in 으로 배열을 출력해보자.
const arr = [1, 2, 3];
arr.x = 10;
for(const i in arr){
console.log(arr[i]); // 1 2 3 10
}
for(const value of arr){
console.log(value); // 1 2 3
}
for ... of문은 배열의 요소만 순회하기 때문에 추가한 프로퍼티는 출력되지 않는다.
const obj = { a: 1, b: 2, c: 3 };
for (const key in obj) {
console.log(obj[key]); // 1, 2, 3
}
for (const value of obj) { // TypeError: obj is not iterable
console.log(value);
}
객체는 이터러블이 아니기 때문에 for ... of를 사용하면 오류가 발생한다.
결론
for ... in문으로 배열을 순회할 수는 있으나, 주의하자 (권장되지 않음)
for ... of문은 배열만을 순회할 수 있다. (객체는 for ... in문으로 순회하자)
출처
1. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in
2. 모던 자바스크립트 Deep Dive
'JavaScript' 카테고리의 다른 글
[JavaScript] ES6 문법 정리 (0) | 2024.05.13 |
---|---|
[JavaScript] 문서 객체 모델, DOM (0) | 2023.04.12 |
[JavaScript] IIFE (즉시 실행 함수) (0) | 2023.04.06 |
[TIL] querySelector와 getElementById의 차이점 (0) | 2023.04.05 |