ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [ JavaScript ] For in 문 VS For of 문
    Computer Science/Aws 2023. 11. 11. 23:02

    1. for in 문

    for in 은 ES1부터 존재했던 방식이며 모든 객체에서 사용이 가능하다.

    다만 해당 값의 value는 가져오지 못하며 key 값만 가져올 수 있다.

    let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
    let object = { name: 'Nam', age: 23, city: 'Seoul' };
    // 0,1,2,3,4,5,6,7,8
    for(let i in arr) {
        console.log(i);
    }
    // name,age,city
    for(let i in object) {
        console.log(i);
    }

     

    더욱이 for in 은 임의로 객체를 순회하여 반환해주기에 순서 등 유의해야한다면 사용하지 말 것을 권장한다.

    2. for of 문

    iterable 한 객체를 순회할 수 있도록 해준다. ES6 부터 추가된 방식이며 for in 과 다르게 value를 반환해 준다.

    let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
    let object = { name: 'Nam', age: 23, city: 'Seoul' };
    // 1,,2,3,4,5,6,7,8,9
    for(let i of arr) {
        console.log(i);
    }
    // error
    for(let i of object) {
        console.log(i);
    }

     

    그렇다면 iterable 한 객체란 무엇인가.

    iterable한 객체는 배열을 일반화한 객체이다. iterable이라는 개념을 사용하면 어떠한 객체든 for of 문을 사용할 수 있다.

    iterable 객체는 Symbol.iterator 라는 메서드가 존재해야한다. 즉 Symbol.iterator가 존재한다면 iterable한 객체라고 할 수 있다.

    Symbol.iterator는 반드시 iterator ( next() 가 존재하는 객체 )를 반환해야하며 for of는 반환된 객체 ( iterator ) 만을 대상으로 동작한다.

    next()의 반환 값은 반드시 { done: Boolean, value: any } 와 같은 형태여야한다. done은 반복이 종료상태를 의미하며 false일 시에는 다음 값이 존재한다는 뜻이고 true 라면 더이상 값이 존재하지 않는다는 뜻이다. 여기서 조금 생각해볼 것은 반환할 것이 없다면 계속 true 여야 한다는 것이다. 즉 next()를 호출한뒤 done 이 true 인 상태에서 또다시 next()를 호출하면 지속적으로 done이 true여야한다.

    한번 객체를 iterable하게 만들어보자.

    let object = { name: 'Nam', age: 23, city: 'Seoul' };
    
    object[Symbol.iterator] = function() {
        let index = 0;
        let keys = Object.keys(this);
        return {
            next: () => {
                return {
                    value: this[keys[index++]],
                    done: index > keys.length
                }
            }
        }
    }
    // Nam, 23, Seoul
    for(let i of object) {
        console.log(i);
    }

    object라는 객체에 Symbol.iterator를 추가하였고 Symbol.iterator는 next()를 반환한다. 또한 next() 는 { value: any, done: Boolean } 을 만족하도록 반환한다.

    위와 같이 구성한다면 기존에는 동작하지 않았던 for of 문이 동작하는 것을 확인할 수 있다.

     

    어렵게 Symbol.iterator를 직접추가하지 않고 iterator 객체로 만들어주는 것이 있다. Generator 함수라는 것이다.

    Generator 함수

    Generator 함수는 iterable 객체를 반환하는 특별한 형태의 함수이다.

    funtion* 형태로 만들며 yield를 순차적으로 반환한다.

    다만 한번만 사용이 가능하며 두번째부터는 사용이 불가능하다.

    let object = { name: 'Nam', age: 23, city: 'Seoul' };
    
    function* objToIter(obj) {
        for(let key of Object.keys(obj)) {
            yield obj[key];
        }
    }
    
    let obj = objToIter(object);
    
    // Nam, 23, Seoul
    for(let i of obj) {
        console.log(i);
    }
    
    // second start , second end ( not in 및 객체 정보 출력 안됨 )
    console.log("second start")
    for(let i of obj) {
        console.log("not in")
        console.log(i);
    }
    console.log("second end")

     

    아래와 같이 next를 직접사용해도 마찬가지이며 해당 next가 {done: Boolean, value: any } 형태로 잘 반환하는 것도 확인할 수 있다.

    let object = { name: 'Nam', age: 23, city: 'Seoul' };
    
    function* objToIter(obj) {
        for(let key of Object.keys(obj)) {
            yield obj[key];
        }
    }
    
    let obj = objToIter(object);
    console.log(obj.next()); // { value: 'Nam', done: false }
    console.log(obj.next()); // { value: 23, done: false }
    console.log(obj.next()); // { value: 'Seoul', done: false }
    console.log(obj.next()); // { value: undefined, done: true }
    
    // 반환 x
    for(let i of obj) {
        console.log("not in")
        console.log(i);
    }

     

    iterable 객체로 만든다면 위와 같이 for of 문을 사용가능할 뿐만아니라 유용한 점들이 생긴다.

    예를들어 spread 연산자, 분해대입 등이 있다.

     

Designed by Tistory.