모든 .forEach를 .map으로 리팩토링

11372 단어 codequalityjavascript
나는 종종 JavaScript 기사를 읽고 많은 기사가 다른 배열 메소드보다 map , filterreduce 에 중점을 둡니다. 현재 React 프로젝트에서 map을 더 많이 사용했지만 무의식적으로 forEach을 여러 번 사용한 것을 알아차리고 더 파고들기로 했습니다.

먼저 두 가지 기능에 대해 알고 있는 내용을 살펴보겠습니다.

.각각


  • 호출된 배열을 탐색하고 각 요소에서 콜백 함수를 실행합니다.
  • 원래 배열을 변경합니다.
  • 정의되지 않은 반환

  • // MDN's example
    
    const array1 = ['a', 'b', 'c'];
    
    array1.forEach(element => console.log(element));
    
    // expected output: "a"
    // expected output: "b"
    // expected output: "c"
    


    .지도


  • 호출된 배열을 탐색하고 각 요소에서 콜백 함수를 실행합니다.
  • 원래 어레이를 변경하지 않음
  • 결과와 함께 새 배열을 반환합니다.

  • // MDN's example
    
    const array1 = [1, 4, 9, 16];
    
    // pass a function to map
    const map1 = array1.map(x => x * 2);
    
    console.log(map1);
    // expected output: Array [2, 8, 18, 32]
    


    우리가 보았듯이 두 기능 모두 똑같은 일을 하며 두 가지 모두 모든 브라우저에서 지원됩니다. 그러나 후드 아래에서 작동하는 방식은 다릅니다.

    차이점



    1. 사용 사례


    map은 원본을 변경하지 않고 새 배열을 반환하므로 반환된 배열을 다른 곳에서 사용할 계획이라면 이 배열을 사용하는 것이 좋습니다. 그러나 원래 배열을 변경하는 데 신경 쓰지 않고 다른 곳에서 사용할 계획이 없다면 forEach을 사용하는 것이 좋습니다. MDN에 따라 :

    You shouldn't be using map if you're not using the array it returns and/or you're not returning a value from the callback.



    2. 접근


    map 의 특성상 좀 더 기능적인 접근을 선호하는 사람들은 선호할 것입니다. 함수형 프로그래밍은 입력을 받고 출력을 반환하는 순수 함수를 사용하여 소프트웨어를 구축하는 접근 방식입니다. 함수형 프로그래밍에서 함수는 범위 밖의 변수를 수정하지 않으며 상태는 공유되지 않으며 데이터는 변경되지 않습니다. 이 접근 방식은 애플리케이션에 도입될 수 있는 버그의 수를 크게 줄입니다.

    3. 성능



    this 게시물에 따르면 mapforEach보다 훨씬 더 성능이 좋은 것 같습니다. 그러나 이후 이 특정 벤치마크에 대해 많은 논란이 있다는 것을 알게 되었습니다. 다음 두 코드를 비교하는 것은 공정하지 않습니다.

    arr.forEach((num, index) => {
        return arr[index] = num * 2;
    });
    



    let doubled = arr.map(num => {
        return num * 2;
    });
    


    첫 번째 예의 return 문은 아무 소용이 없기 때문입니다. 또한 이러한 기능의 성능은 다른 브라우저에서 JavaScript 엔진의 구현에 따라 달라지므로 비교가 그렇게 간단하지 않습니다.

    4. 비동기 프로그래밍



    MDN 에 명시된 바와 같이 forEach은 콜백이 동기식일 것으로 예상하므로 멋진 비동기 코드와 잘 작동하지 않습니다. 그러나 map은 더 관대합니다.

    리팩토링



    내 프로젝트에서 forEach을 사용하여 다음과 같은 내 라운드 배열을 반복했습니다.

    "rounds": [
    {
        "artists": [
        {
            "name": "Three Days Grace",
        },
        {
            "name": "IDK",
        },
        ...
        ]
    },
    ...
    ]
    


    현재 라운드의 아티스트 이미지가 포함된 문자열 배열이 있으며 각 아티스트를 반복하고 객체에 image 속성을 추가하고 싶었습니다. 이것이 내가 처음으로 달성한 방법입니다.

    const artistImages = getArtistData(artistData); // returns an array of strings
    rounds.forEach((round, index) => {
       round.artists[currentRound].image = artistImages[index];
    });
    return rounds;
    


    구성 요소에서 이 함수를 호출한 다음 반환된 배열을 상태로 할당했습니다. 이제 상태는 다음과 같았습니다.

    "rounds": [
    {
        ...
        "artists": [
        {
            "name": "Three Days Grace",
            "image": "https://i.scdn.co/image/2a9ec8d494f8d0a52fd67c3239efc2b9e79a4ced"
        },
        {
            "name": "IDK",
            "image": "https://i.scdn.co/image/6594334f1d1a2e65394d27eb457ccff203886411",
        },
        ]
    },
    ...
    ]
    

    map을 사용하기 위한 리팩토링은 매우 간단했고 동일한 결과를 얻었습니다. 정확히 같은 코드 줄이지만 이제 map 내부에 무언가를 반환하고 변수에 저장한 다음 해당 변수를 내 구성 요소에 반환합니다.

    const artistImages = getArtistData(artistData); // returns an array of strings
    const roundsWithImages = rounds.map((round, index) => { 
       round.artists[currentRound].image = artistImages[index];
       return round;
    });
    
    return roundsWithImages;
    


    이제 내 코드가 조금 더 읽기 쉽고 돌연변이된 변수로 인해 엉망이 될 가능성이 조금 더 작기를 바랍니다!

    읽어 주셔서 감사합니다. 이 기사를 개선할 수 있는 방법을 알려주세요. 다음시간까지 👋

    Unsplash에서 Oliver Hale의 표지 사진.

    좋은 웹페이지 즐겨찾기