ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 다시 봐도 헷갈리는 배열 메소드 정리_filter, map, forEach
    Language/JavaScript 2022. 10. 21. 21:50

    배열 메소드를 공부하고 돌아서면 까먹는다.

    화.난.다.정.말

     

    이 메소드가 배열을 반환하는지, 평가만 하는지 혼란스럽고 결국 MDN을 찾아보게 된다.

    물론 언제든지 메소드를 사용할 때 찾아보면서 코딩하면 되겠지만, 언제까지나 그럴 수는 없다.

     

    그래서 이참에 이번 프리코스 기간동안 나를 괴롭혔던 배열 메소드를 정리해본다.

     

    1. filter()

    • filter 메소드는 주어진 조건에 맞는(함수의 return을 true로 만드는) 요소 전체를 담은 배열을 반환한다. 어떠한 요소도 테스트를 통과하지 못하면 빈 배열을 반환합니다.
    • filter는 배열 내 요소를 탐색해서 원하는 요소를 뽑아낼 때 사용합니다.
    • 함수명 그대로 필터링 하는 것이죠.
    let results = arr.filter(function(item, index, array) {
      // 조건을 충족하는 요소는 results에 순차적으로 더해집니다.
      // 조건을 충족하는 요소가 하나도 없으면 빈 배열이 반환됩니다.
    });
    
    // 예시
    
    let users = [
      {id: 1, name: "John"},
      {id: 2, name: "Pete"},
      {id: 3, name: "Mary"}
    ];
    
    // 앞쪽 사용자 두 명을 반환합니다.
    let someUsers = users.filter(item => item.id < 3);
    
    console.log(someUsers.length); // 2
    

    2. map()

    • map 메소드는 배열 내의 모든 요소 각각에 대해 주어진 함수를 호출한 결과를 모아 새로운 배열을 반환합니다.
    • 따라서, map메소드를 돌렸을 때 반환되는 배열의 요소는 원 배열의 요소 갯수와 같습니다. filter 메소드를 통해 반환된 배열은 원 배열의 요소 갯수보다 적게 요소를 가질 수 있죠. 필터링 된거니까요.
    • 즉, map 매소드는 배열 요소를 특정 규칙에 따라 변형하고 싶을 때 사용합니다.
    let result = arr.map(function(item, index, array) {
      // 모든 요소를 함수의 인자로 input한 결과를 요소로 담아 배열로 반환합니다.
    });
    
    // 예시
    
    let name = ["Bilbo", "Gandalf", "Nazgul"]
    let lengths = name.map(item => item.length);
    console.log(lengths); // [5,7,6]
    

    3. forEach()

    • forEach 메소드는 주어진 함수를 배열 요소 각각에 대해 실행합니다.
    // 문법
    arr.forEach(function(item, index, array) {
     /* [매개변수] 
    - callback : 각 요소에 대해 실행할 함수. 다음 세 가지 매개변수를 받습니다.
    	currentValue : 처리할 현재 요소.
    	index : 처리할 현재 요소의 인덱스.<
    	array : forEach()를 호출한 배열.
    - thisArg : callback을 실행할 때 this로 사용할 값.
    
    **[반환 값]
    undefined.**
    
    [설명]
    forEach()는 주어진 callback을 배열에 있는 각 요소에 대해 오름차순으로 한 번씩 실행합니다.
    삭제했거나 초기화하지 않은 인덱스 속성에 대해서는 실행하지 않습니다. (예: 희소 배열)
    */
    });
    
    let name = ["Bilbo", "Gandalf", "Nazgul"]
    let lengths = name.forEach(item => item.length);
    console.log(lengths); // undefined
    
    // for 문으로도 표현하면 하단과 같다.
    for (let i = 0; i < name.length; i++) {
    	name[i].length
    }
    console.log(nameLength) // undefined

    forEach 메서드는 단순히 반복문을 대체하기 위한 함수이고,

    map 메서드는 요소값을 다른 값으로 mapping한 새로운 배열을 생성하기 위한 고차함수다.

    위 map 메소드의 예제를 그대로 forEach에 그대로 넣고, lengths 변수에 할당해보자.

     

    콘솔로 찍어보면 undefined가 출력된다.

    왜 일까?

    말 그대로 함수를 각 요소에 대해 실행만 시켰기 때문이다.

    forEach는 배열을 자동적으로 반환하는 메소드가 아니다.

     

    즉, **forEach** 메소드는

    (1) 함수를 각 요소에 실행만 하고,

    (2) 그 결과 값을 새로운 배열로 반환하지 않는다.

     

    이와는 다르게 **map** 메소드는

    (1)과 (2)의 과정이 모두 포함된 메소드인 것이다.

     

    그래서, 단순히 for문을 대체하기 위해 forEach를 사용한다면 예제처럼 lengths라는 변수에 할당할 필요가 없다.

    for문을 변수에 할당한다는 것은 매우 어색하지 않은가?

     

    한편, map 메소드와 같은 결과를 얻기 위해서는 forEach 메소드의 콜백함수 내부에 배열을 반환하도록 조작해주어야 한다.

    즉 (2)의 과정을 추가해주어야 한다.

    let name = ["Bilbo", "Gandalf", "Nazgul"]
    let nameLength = [];
    
    name.forEach( (ele, i) => nameLength[i] = ele.length);
    console.log(nameLength); // [5,7,6]
    
    
    // for 문으로도 표현하면 하단과 같다.
    for (let i = 0; i < name.length; i++) {
      nameLength[i] = name[i].length
    }
    console.log(nameLength) // [5,7,6]

     

    댓글