본문 바로가기
Language/JavaScript

[JS] for...in 과 for...of의 차이

by eess 2024. 6. 28.

 

 

for...in 과 for...of의 차이에 대해 알아보겠습니다.

 

for...in

  • for...in 문은 상속된 열거 가능한 속성들을 포함하여 객체에서 문자열로 키가 지정된 모든 열거 가능한 속성에 대해 반복합니다.
for (variable in object) {
  statement;
}

 

열거 가능한 속성(enumerable)

객체를 선언하여 살펴보면 [[Prototype]]이라는 것이 있습니다.

  • 객체를 선언하여 살펴보면 [[Prototype]] 이라는 것이 있습니다.
  • 열거 가능한 속성이 무엇인지 이해하기 위해 Prototype에 대해 먼저 정리해보겠습니다.

 

Prototype

  • JS는 프로토타입 기반 객체지향언어이며, 프로토타입 체인을 통해 속성을 상속합니다.
  • JS의 모든 객체는 부모 역할의 객체와 연결되어 있어, 부모 객체의 프로퍼티 또는 메소드를 상속받아 사용할 수 있습니다.
  • 이러한 부모 객체를 프로토타입(Prototype)이라 합니다.
  • 직접 생성한 속성은 기본적으로 열거 가능하며, 프로토타입 체인을 통해 상속받은 속성은 속성 명세의 enumerable 값에 따라 달라집니다.

enumerable

  • Object.getOwnPropertyDescriptor() 함수를 사용하여 enumerable 값을 확인할 수 있습니다.
  • enumerable: false 라면 열거 가능하지 않은 속성이며, enumerable: true 라면 열거 가능한 속성입니다.
  • 아래와 같이 toString 메서드는 열거 가능하지 않은 속성이기에 for...in 루프로 객체 속성을 반복하더라도 toString은 나오지 않는 것입니다.
const desc = Object.getOwnPropertyDescriptor(Object.prototype, "toString");

console.log(desc);

/*
{ value: [Function: toString],
  writable: true,
  enumerable: false,
  configurable: true }
*/

 

  • 프로토타입으로부터 열거 가능하지 않은 속성을 상속받았으나 프로토타입 체인 상에 있는 속성과 객체 자체에 있는 속성이 충돌한다면, 객체 자체의 프로퍼티를 우선합니다.
  • 아래와 같이 객체 안에서 toString을 새롭게 작성했을 경우, 이는 프로토타입 체인 상의 toString과 충돌하기에 커스텀한 toString이 우선시 되어 for...in 루프에서 반복할 수 있는 것입니다.
const obj = {
  a: 1,
  b: 2,
  toString: function () {
    console.log("Custom toString");
  },
};

for (const key in obj) {
  console.log(obj[key]);
  /*
  1
  2
  ƒ () {
    console.log('Custom toString');
  }
  */
}

 

 


 

for...of

  • for...of 문은 반복가능한 객체(Array, Map, Set, String, TypedArray, Arguments 객체 등)에 대해서 반복합니다.
  • [Symbol.iterator] 속성이 있는 모든 컬렉션 요소에 대해 반복합니다.

for (variable of iterable) {
  statement;
}

 

[Symbol.iterator] 속성

  • 배열을 선언하여 살펴보면 Symbol.iterator 속성이 있습니다.
  • [Symbol.iterator] 속성을 이해하려면 이터레이션 프로토콜을 먼저 이해해야 합니다.

 

이터레이션 프로토콜(iteration protocol)

  • ES6에서 도입된 이터레이션 프로토콜(iteration protocol)은 데이터 컬렉션을 순회하기 위한 프로토콜(미리 약속된 규칙)입니다.
  • 이터레이션 프로토콜을 준수한 객체는 for…of 문으로 순회할 수 있고 Spread 문법(...)의 피연산자가 될 수 있습니다.
  • 이터레이션 프로토콜에는 이터러블 프로토콜(iterable protocol)과 이터레이터 프로토콜(iterator protocol)이 있습니다.
    • 이중에서 이터러블 프로토콜을 준수한 객체이터러블(iterable)이라 합니다.
    • 이터러블 프로토콜을 따르는 객체는 반드시 Symbol.iterator 메서드를 구현하거나 프로토타입 체인에 의해 상속해야 합니다.

 

 그럼 다시 [Symbol.iterator] 이야기로 돌아가보겠습니다.

  • ES6에서 제공하는 빌트인 이터러블에는 Array, String, Map, Set, TypedArray(Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array), DOM data structure(NodeList, HTMLCollection), Arguments가 있습니다.
  • 이러한 요소들의 속성을 살펴보면 Symbol.iterator가 있습니다. 즉, for...of로 순회할 수 있다는 뜻입니다.

 

결론

  • 객체의 속성을 반복할 때는 for...in을 사용합니다.
  • 배열, 문자열, Map, Set 등을 반복할 때는 for...of를 사용합니다.

 

참고

 

'Language > JavaScript' 카테고리의 다른 글

parseInt( ) vs Number( )  (0) 2024.08.27
[JS] JavaScript의 일급객체란?  (0) 2024.07.05