본문 바로가기

항해99_10기/105일의 TIL & WIL

[3주차] [20221127] for, for in, for of

오늘은 for in과 for of의 차이에 대해 알아보았고, for문이 있는데 왜 등장했는지도 간접적으로 알아보았다.

깔끔하게 잘 정리되어 있는 자료를 찾지 못해서 MDN에 나와있는 내용을 기반으로 대략 정리했다.

 

우선, for..in이 언제부터 추가되었는지는 잘 모르겠지만, for..of문은 ES6부터 추가되었다. ES6에서는 새로운 Symbol primitive가 추가되었고, 이를 대응하기 위해서 for..of문이 추가된 것이다. 이 외에도 ES6로 넘어오면서 지금 우리가 편하게 쓰는 대부분의 JS 기능이 추가되었는데, 대표적으로 let, const, template literal, Map, Promise, Class 등이 있다.

 

JavaScript가 어떻게 만들어졌고, 변해왔는지는 아래 유튜브에 재미있게 설명되어 있다.

 

 

 

  • for...in
    • 상속된 열거 가능한 속성들을 포함하여 객체에서 문자열로 키가 지정된 모든 열거 가능한 속성에 대해 반복
      • 열거 가능한 non-Symbol 속성에 대해서만 반복
      • Symbolkey가 지정된 속성은 무시됨
      • for...in반복문은 정수가 아닌 이름을 가진 속성, 상속된 모든 열거 가능한 속성들을 반환
    • for..in은 임의의 순서로 객체의 속성들에 대해 반복하므로, 순서가 보장되지 않음
      • 방문의 순서가 중요한 배열의 반복시에는 숫자 인덱스를 사용할 수 있는 for 이나, for...of 또는 Array.prototype.forEach() 사용을 권장
    • for..in의 사용처??
      • 쉽게 객체의 속성을 확인할 수 있기 때문에, 디버깅을 위해 사용 가능
      • key-value쌍 자료특정 value를 가진 key가 있는지 확인하려는 경우 사용 가능

 

  • for...of
    • iteralbe 객체의 값에 대해 동작하며, 한 번에 한 개씩, 순차적으로 방문
      • iterable 하기 위해서는 object가 Symbol.iterator key의 속성을 가져야 한다는 것을 의미 {[Symbol.iterator] : object를 반환하는, arguments 없는 function. iterator protocol을 따른다.}
      • for...of는 iterable을 순회할 때, 먼저 iterable의 [[@@iterator]()] 메서드를 호출하고, 해당 메서드는 iterator를 반환하며, 반복적으로 반환 값인 iterator의 next() 메서드를 호출하여 value를 변수로 지정하기 위해 순서를 부여함
    • for...of 의 사용처??
      • ES6에 추가된 새로운 컬렉션(Symbol.iterator를 말하는 것 같음) 전용 반복 구문
      • (주로) 배열의 요소 값(value)를 순차적으로 방문해야 할때 사용
      • iterable 객체의 value에만 접근이 가능하고, 객체의 property에는 접근 불가
  • for...in 과 for...of 사용법의 차이를 보여주는 예제
    • 아래 예제에서는 Obejct와 Array prototype으로 objCustom 메서드와 arrCustom 메서드를 추가
    • 그래서 for..in 문에서 array이자 object인 iterable의 property를 모두 찍어주고 있음
      • console.log(iterable)을 찍어보면, arrCustom과 objCustom은 각각 [[Prototype]] : Array와 [[Prototype]] : Object에 숨겨져 있음
    • 또, 두번째 for..in문에서는 Obejct.hasOwn(instance, prop) 메서드를 사용하여, 상속하였거나, 존재하지 않는 property를 제외하고 iterable 배열의 직접(?) 속한 property인 경우, console.log로 찍어주고 있음
      • objCustom과 arrCustom은 상속된 값이므로 제외
    • 하지만, iterable의 value에만 접근이 가능한 for..of문의 경우, ㅇ
Object.prototype.objCustom = function () {};
Array.prototype.arrCustom = function () {};

const iterable = [3, 5, 7];
iterable.foo = "hello";

console.log(iterable) // [3, 5, 7, foo: 'hello']

for (const i in iterable) {
  console.log(i);
}
// "0", "1", "2", "foo", "arrCustom", "objCustom"

for (const i in iterable) {
  if (Object.hasOwn(iterable, i)) {
    console.log(i);
  }
}
// "0" "1" "2" "foo"

for (const i of iterable) {
  console.log(i);
}
// 3 5 7