4-20 반복문에 대해 질문이있습니다

조회수 1110회

전에 해주신 답변 감사합니다

그런데 4-20반복문에서 for of라는 반복문은 배우지 않았지만

강의 링크를 읽다보니까 궁금한게 생겼습니다

let arr = [3, 5, 7]; arr.foo = "hello";

for (let i in arr) { console.log(i); // logs "0", "1", "2", "foo" }

for (let i of arr) { console.log(i); // logs "3", "5", "7" }

for in 문에서는 foo가 속성 값으로 들어가 있어서 hello라는게 나오는데

왜 for of 문 에서는 'hello'로 값이 안나오는 건가요?

1 답변

  • 좋아요

    0

    싫어요
    채택 취소하기

    안녕하세요. 성중원님 :-)

    이전에 올리신 질문들 답변 확인 하셨군요! 그럼 답변 내용이 적절한 경우, 채택 부탁드립니다. fast-frontend 태그로 묶인 질문은 다른 수강생 분들도 참고하고 있거든요. 질문자가 채택한 답변은 그만큼 신뢰 되는 답변이 될 수 있으니 좋은 지표가 될 수 있습니다.

    1. <img> 태그 속성에 대한 질문입니다.
    2. [4-14] 강의에서 작성하신 코드에 궁금한게 있습니다.

    그럼 질문에 답변 드립니다.

    먼저 질문 주신 for-of문은 ECMAScript 2015(이하 ES6)에 새롭게 추가된 구문입니다. 관련 강의는 [6-12] for-of 문/이터레이션 프로토콜/제너레이터 영상 강의를 통해 자세히 공부하실 수 있습니다.

    이어서 문의 주신 코드 구문을 살펴보겠습니다.

    // JavaScript 리터럴을 사용해 배열 객체 생성
    let arr = [3, 5, 7]; 
    
    // 객체의 속성 foo 추가
    arr.foo = "hello";
    
    // for-in문을 사용해 배열 객체 순환
    for ( let i in arr ) { console.log(i); }
    // 출력: "0", "1", "2", "foo"
    
    // for-of문을 사용해 배열 이터레이터 객체 순환
    for ( let i of arr ) { console.log(i); }
    // 출력: "3", "5", "7"
    

    제가 남긴 주석을 잘 보면 차이가 있는 것을 눈치 챘을 겁니다. 이 점이 결과의 차이를 가져온 것입니다. 그 다른 점이란 다음과 같습니다.

    object Array   vs   object Array Iterator
    

    요컨대 배열 객체배열 이터레이터 객체는 성질이 다른 객체 이기에 결과 또한 다른 것입니다. 간단히 말해 배열 객체를 순환 처리 했던 for-in문과 달리 for-of문은 배열 이터레이터 객체를 순환 처리합니다.

    뭔가 접하지 못했던 것이 등장했네요. 그럼 배열 이터레이터 객체는 무엇 일까요? 먼저 이를 증명해보겠습니다.

    사용자는 편의상 다음과 같이 작성했지만

    for (let i of arr) { console.log(i);}  
    

    내부적으로 작동되는 코드는 다음과 같습니다.

    for (let i of arr[Symbol.iterator]()) { console.log(i);}  
    

    arr[Symbol.iterator]()를 console 패널에서 확인하면 Array Iterator {}가 출력되는 것을 확인할 수 있을 겁니다.

    arr[Symbol.iterator](); // Array Iterator {}
    

    Iteration Protocol

    ES6부터는 이터레이션 프로토콜과 같은 새로운 프로토콜이 추가되었습니다. 자세한 설명은 영상 강의를 통해 공부해보시고, 아래 도표를 참고하면 for-of문은 Iterable 프로토콜을 인터페이스로 사용하는 것을 알 수 있습니다. Arrays는 데이터 소스라고 표기하고 있습니다. (출처: Exploring ES6)

    이터러블, 이터레이터, 이터레이터 결과 인터페이스는 다음의 조건에 따릅니다. 즉, 이터러블은 [Symbol.iterator] 메소드 속성을 반드시 가져야 하며, 실행 시 이터레이터 객체를 반환합니다. 이터레이터는 next() 메서드를 반드시 가져야 하고, 실행 시 이터레이터 결과 객체를 반환해야 합니다. 그리고 이터레이터 결과 객체는 항상 value, done 속성을 가집니다.

    interface Iterable {
      [Symbol.iterator]() : Iterator;
    }
    interface Iterator {
      next() : IteratorResult;
    }
    interface IteratorResult {
      value: any;
      done: boolean;
    }
    

    이 조건에 충족하면 이터레이터 객체입니다. (자세한 내용은 영상 강의 참고)

    arr 변수에 참조된 배열 객체의 [Symbol.iterator] 메서드 속성은 배열 이터레이터 객체를 참조합니다. 확인하는 방법은 다음과 같습니다.

    arr[Symbol.iterator].toString(); // "function values() { [native code] }"
    

    배열 객체를 통해 배열 이터레이터 객체를 추출하는 방법은 다음과 같습니다.

    let arr_iterator = arr[Symbol.iterator](); // Array Iterator {}
    

    추출된 배열 이터레이터 객체는 for-of문을 통해 순환 가능합니다.

    for (let v of arr_iterator) {
      console.log(v); // 출력: 3, 5, 7
    }
    

    이러한 일련의 과정을 for-of문에 배열 객체를 전달하면 자동으로 처리해줍니다. 그래서 아래와 같은 구문이 가능한 것입니다.

    for (let v of arr) {
      console.log(v); // 출력: 3, 5, 7
    }
    

    그럼 다시 본론으로 돌아와서 질문에 답변해보겠습니다.

    Q

    for-in문과 for-of문은 결과가 다른가?

    A

    for-in문은 객체를 순환 처리하기 위한 구문입니다. 그런데 배열은 이 구문을 사용해 순환 처리하기 적합하지 않습니다. 이유는 for-in문이 객체의 속성을 모두 순환하는 구조를 가지기 때문입니다.

    arr.foo 속성은 배열 객체의 속성이지만, 배열 아이템은 아닙니다. 그래서 length 값에 아이템이 아닌 속성 값은 포함되지 않습니다. 이를 통해 JavaScript 배열이 객체로서 속성을 가질 수는 있지만, 아이템으로 추가되지 않는다는 사실을 확인할 수 있습니다. JavaScript 함수 또한 객체로 속성을 가질 수 있습니다.

    function pick(){}
    pick.bar = 'pick 함수 객체의 bar 속성';
    

    질문은 for-of문과의 차이점을 질문 했지만, 사실 for문과의 차이점 이기도 합니다. 아래 구문을 살펴보세요. for-of문과 동일하고, for-in문과는 차이가 있죠.

    for (let k=0, j=arr.length; k < j; k++) {
      console.log(arr[k]); // 출력: 3, 5, 7
    }
    

    배열 객채를 통해 순환 처리한다면 당연 포함된 아이템 만으로 한정지어져야 합니다. 하지만 for-in문은 객체 속성 모두를 순환 처리하죠. 이 점에 배열 순환 시, for-in문을 사용하면 안되는 이유 중 하나 입니다.

    더 나아가면 문자, 배열, 유사 배열 데이터만 순환 처리하는 for문과 달리 for-of문은 오직 이터러블 데이터는 모두 순환 처리 가능합니다. 처리 가능한 이터러블 데이터는 다음의 영상 강의를 통해 배우실 수 있습니다.

    • (•́ ✖ •̀)
      알 수 없는 사용자

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)