for...infor...of는 생김새가 비슷해서 처음에 정말 헷갈립니다. 면접에서도 자주 나오는 질문인데, 핵심은 "in은 키, of는 값" 입니다.

for...in — 객체의 키를 순회

for...in은 객체의 열거 가능한(enumerable) 프로퍼티 키 를 순회합니다.

JS
const user = { name: "정훈", age: 25, job: "개발자" };

for (const key in user) {
  console.log(`${key}: ${user[key]}`);
}
// name: 정훈
// age: 25
// job: 개발자

프로토타입 체인까지 순회하는 문제

JS
function Person(name) {
  this.name = name;
}
Person.prototype.greet = function () {
  return "안녕!";
};

const person = new Person("정훈");

for (const key in person) {
  console.log(key); // "name", "greet" — 프로토타입의 메서드까지 나옴!
}

// hasOwnProperty로 필터링
for (const key in person) {
  if (Object.hasOwn(person, key)) {
    console.log(key); // "name"만 출력
  }
}

이런 문제 때문에 객체 순회에는 Object.keys()를 쓰는 것이 더 안전합니다.

배열에 for...in을 쓰면 안 되는 이유

JS
const arr = ["a", "b", "c"];

for (const index in arr) {
  console.log(typeof index); // "string" — 인덱스가 문자열!
  console.log(index);        // "0", "1", "2"
}

// 배열에 프로퍼티를 추가하면 같이 순회됨
arr.customProp = "oops";
for (const key in arr) {
  console.log(key); // "0", "1", "2", "customProp"
}

배열에는 for...of나 배열 메서드를 사용해야 합니다.

for...of — 이터러블의 값을 순회

for...of이터러블(iterable) 프로토콜 을 구현한 객체의  을 순회합니다.

JS
const arr = ["사과", "바나나", "체리"];

for (const fruit of arr) {
  console.log(fruit); // "사과", "바나나", "체리" — 값을 직접 얻음
}

// 문자열도 이터러블
for (const char of "Hello") {
  console.log(char); // "H", "e", "l", "l", "o"
}

// Map
const map = new Map([
  ["a", 1],
  ["b", 2],
]);
for (const [key, value] of map) {
  console.log(`${key}: ${value}`);
}

// Set
const set = new Set([1, 2, 3]);
for (const value of set) {
  console.log(value);
}

일반 객체는 for...of로 순회 불가

JS
const obj = { a: 1, b: 2 };

// TypeError: obj is not iterable
for (const value of obj) {
  console.log(value);
}

// 대안: Object.entries()와 함께 사용
for (const [key, value] of Object.entries(obj)) {
  console.log(`${key}: ${value}`);
}

이터러블이란?

Symbol.iterator 메서드를 가진 객체입니다.

JS
// 내장 이터러블들
const iterables = [
  [1, 2, 3],           // Array
  "hello",             // String
  new Set([1, 2]),     // Set
  new Map(),           // Map
  // NodeList, arguments 등도 이터러블
];

// 커스텀 이터러블 만들기
const range = {
  from: 1,
  to: 5,
  [Symbol.iterator]() {
    let current = this.from;
    const last = this.to;
    return {
      next() {
        return current <= last
          ? { value: current++, done: false }
          : { done: true };
      },
    };
  },
};

for (const num of range) {
  console.log(num); // 1, 2, 3, 4, 5
}

for...of에서 인덱스가 필요할 때

JS
const fruits = ["사과", "바나나", "체리"];

// entries()로 인덱스 + 값
for (const [index, fruit] of fruits.entries()) {
  console.log(`${index}: ${fruit}`);
}

// keys()로 인덱스만
for (const index of fruits.keys()) {
  console.log(index);
}

// values()로 값만 (기본 동작과 동일)
for (const fruit of fruits.values()) {
  console.log(fruit);
}

break, continue, return

for...offor...in 모두 breakcontinue를 사용할 수 있습니다. forEach와의 중요한 차이점입니다.

JS
const numbers = [1, 2, 3, 4, 5];

// for...of에서 break 사용 가능
for (const num of numbers) {
  if (num === 3) break;
  console.log(num); // 1, 2
}

// forEach에서는 break 사용 불가!
numbers.forEach((num) => {
  if (num === 3) return; // break가 아님, 해당 반복만 스킵
  console.log(num); // 1, 2, 4, 5
});

비교 표

특성for...infor...of
순회 대상열거 가능한 프로퍼티 키이터러블의 값
반환값키 (문자열)
배열비권장 (인덱스가 문자열)권장
객체사용 가능 (주의 필요)직접 사용 불가
프로토타입순회함순회 안 함
break/continue가능가능

어떤 반복문을 쓸까?

JS
// 배열 순회 → for...of 또는 배열 메서드
for (const item of array) { /* ... */ }
array.forEach((item) => { /* ... */ });

// 객체 순회 → Object.keys/entries + for...of
for (const [key, value] of Object.entries(obj)) { /* ... */ }

// 인덱스 기반 반복 → 전통 for
for (let i = 0; i < array.length; i++) { /* ... */ }

// 조건부 중단이 필요 → for...of 또는 전통 for
for (const item of array) {
  if (condition) break;
}

**기억하기 **: "in은 key(인), of는 value(오브)". for...in은 객체 전용(배열에 쓰지 마세요), for...of는 이터러블 전용입니다. 배열은 for...of, 객체는 Object.entries() + for...of가 가장 안전합니다.

댓글 로딩 중...