ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Javascript] es6 함수들 도중 break?
    Front-end/Javascript 2020. 5. 5. 18:03
    반응형

    Javascript와 es6

     최근 node.js와 Vuex기반 프로젝트 기능을 개발하고 테스트 하던 중, 생각하지도 못한 버그가 발생하였다. es6의 Array.map, Array.filter, Array.reduce 등의 함수들은 많은 개발자들의 수고를 덜어주고 있다. for loop으로 했어야 할 코드가 훨씬 가독성 있고, 깔끔해지기 때문에 나 또한 선호하는 편이다.

     이 함수들이 어떻게 만들어졌는지 보지 않고 쓰다가 결국 삽질을 하게 되었다.

     


    시작된 삽질

     

    다음과 같은 코드를 작성하면 어떤 결과를 보여줄까?

    const testArray = [{"A": "a"}, {"B": "b"}, {"C": "c"}]
    
    //Case1
    testArray.map(item => {
     const key = Object.keys(item)[0]
     if(key === "B") {
       break
     } else {
       let tmp = {}
       tmp[item[key]] = key
       return tmp
    })
    
    result: error, Illegal break statement
    
    //Case2
    testArray.map(item => {
     const key = Object.keys(item)[0]
     if(key === "B") {
       return false
     } else {
       let tmp = {}
       tmp[item[key]] = key
       return tmp
     }
    })
    
    result: [{a: "A"}, false, {c: "C"}]

      Case1에서는 key가 "B"이면 testArray.map의 iterator를 멈추고자 break를 썼지만, illegal break statement 에러가 발생한다. 다시 한번 삽질을 시도한다. Case2처럼 return false로 대체하면 정말 false 값을 map 결과에 넣어주게 된다. 음.. 이런걸 원하는게 아니었을텐데...?

     

     MDN 도큐먼트를 보기로 한다...

    Description

    map calls a provided callback function once for each element in an array, in order, and constructs a new array from the results. callback is invoked only for indexes of the array which have assigned values (including undefined).

     

    아... 주어진 input array의 길이만큼 iterator를 돌리면서 그때마다 callback를 돌리는 듯 하다. Hoxyna가 역시나가 되었다. callback을 호출하는 순간 Loop의 임무는 사실 끝난 것이다.

     


    Array.map polyfill


    브라우저에서 es6를 지원하지 않는 경우에 우리는 babel Polyfill을 사용하거나, 직접 polyfill을 만들어 넣기도 한다.

    Array.prototype.map의 간단한 polyfill은 다음과 같다. 위에서 보았던 것처럼 for loop는 callback을 호줄 하면서 이미 다음 인덱스에 바통을 넘긴다. break이 유효할리가 없던 것이다.

    if (!Array.prototype.map) {
     Array.prototype.map = function(callback) {
        let newArray = [];
         // iterate array elements
        for(let item of this) {
        // pass each element to callback and push response to new array
          newArray.push(callback(item));
        }
        // return final array
        return newArray;
      }
    }

    결론

    결국, es6에서 사용하는 Array의 주된 함수들은 iterator를 도중에 멈추고 싶다면, for loop으로 코드를 다시 작성할 것을 추천한다.

    Map.prototype.forEach의 경우 every와 같은 함수로 우회할 때도 있지만, 역시 정석이 더 마음에 편할 것 같다.


    참고

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map

    https://medium.com/@billingpuneet.13/how-to-write-polyfill-for-array-map-in-javascript-5d692a1b960a

    반응형

    댓글

Designed by Tistory.