JavaScript Array의 고차원 함수들

블레어(blair)·2020년 7월 26일
1

JavaScript

목록 보기
4/4
post-thumbnail

forEach, map, filter, reduce

  • 일단 네가지 메소드의 공통점은 배열에 대한 고차원 함수이며, 기존의 배열을 건드리지 않고 반복문을 실행한다. 즉 기존의 배열에 불변성을 주면서 반복문을 실행할 수 있는 것 이다.
  • 하지만 위 함수들은 모두 각기 역할과 내용이 달라서 상황에 따라서 적절히 사용하는 것이 중요한 것 같다. 그래서 어떤 차이점들이 있는지 공부해보았다.
  • (가장 흔한 반복문으로는 for문이 있지만 이것은 배열에 대한 메소드는 아니고 그저 블록문 안에서 배열을 돌며 입력된 코드가 실행되는 것 뿐이다.)

.forEach() VS .map()

const arrMap = [1, 2, 3, 4, 5];
const result = arrMap.map(num => { return num +'하이'});

const arrForEach = [1, 2, 3, 4, 5];
const result2 = arrForEach.forEach(num => { return num * 3});

console.log(result) // ["1하이", "2하이", "3하이", "4하이", "5하이"]
console.log(result2) // undefined => 실행은 되지만 리턴되는것은 없다.

즉 .forEach()는 리턴값이 없다

// 때문에 forEach메소드가 진행된 결과를 따로 배열로 받기 위해서는 새 배열을 만들고 거기에 push를 하면서 돌아야한다.
let tmpArr = [] // 새 배열을 만들고
arrForEach.forEach(num => { tmpArr.push(num + '하이')}); // 진행하면 tmpArr에 저장이 되겠지?
console.log(tmpArr) // ["1하이", "2하이", "3하이", "4하이", "5하이"]
  • 즉 두 메소드 다 특정 배열을 돌면서 내부함수의 내용을 실행하는것은 맞지만 map은 모두 실행되고난 후 새로운 배열이 리턴되지만 forEach는 실행만 할뿐 새 배열을 리턴하진 않는다.
  • 그렇다면 forEach는 메소드라는 점 말고는 for문과의 차이점이 없는 것 아닐까???

.filter()

  • array를 돌면서 조건에 맞는 원소들만 걸러내서 새 배열에 담아 리턴해낸다.
const array1 = [1, 2, 3, 4];
const result = array1.filter((val) => val > 2)

console.log(result) // [3, 4]

.reduce()

  • reduce메소드의 내부 구성은 콜백함수와, 초기값이 들어올 수 있다.
    => array.reduce(콜백함수,초기값)
  • 콜백함수의 인자는 4가지가 있다.
    1.acc(누적된 현재상태)
    2.cur(원본배열의 현재원소)
    3.idx(원본배열의 현재인덱스) // 옵션
    4.src(원본) // 옵션
    => array.reduce((acc,cur,idx,src) ⇒ (),초기값)
  • 리턴되는 것은 ? array를 돌면서 콜백함수를 실행한 후 축적된 최종결과를 리턴한다.
// <간단한 예시1>
const array1 = [1, 2, 3, 4];
const result1 = array1.reduce((accumulator, currentValue) => accumulator + currentValue,5); 

console.log(result1) // 15


// <조금은 복잡한 예시2>
const array2 = ['모모', '콩이', '보리', '블레어']

let result2 = array2.reduce((acc,cur,idx,src) => {
            acc.push(`cur:${cur} idx:${idx} src[0]:${src[0]}`)
            
            return acc
            },[])

// recude돌면서 만들어진 새 배열을 불러옴
console.log(result2) // ["cur:모모 idx:0 src[0]:모모", "cur:콩이 idx:1 src[0]:모모", "cur:보리 idx:2 src[0]:모모", "cur:블레어 idx:3 src[0]:모모"]

reduce는 특별하다.

reduce의 return 형태는 다양하다.

  • 초기값이 어떤 형태냐에 따라서 return형태도 다르다는 것 이다.
    즉 초기셋팅이 new Map()이라면 리턴값을 반복들이 축적된 Map이 리턴되는 것이다.
    * 같은맥락으로 리듀스는 결과가 Object, Set, Array, Number, String....
    등의 다양한 결과가 리턴될 수 있다.

reduce로 filter, map을 구현할 수 있다.

profile
프론트엔드 개발자 블레어의 개인 블로그 입니다. 개발공부를 하며 나누고 성장하고 싶습니다 :)

1개의 댓글

comment-user-thumbnail
2020년 7월 27일

https://eloquentjavascript.net/2nd_edition/05_higher_order.html
이 글도 참고해보시면 좋을 것 같아요.

forEach는 반환값 없이 함수 연산을 계속 실행하고, forEach를 쓰는 이유는 반환 값이 필요 없는 경우에 사용하신다고 생각하시면 될 것 같아요. 그래서 자바 책에서는 종단연산이라고 해요.

list.map(n => {return n + 1}).filter(n => n % 2 === 0).forEach(n => {console.log(n)});

제가 자바스크립트는 익숙치 않아서 ㅎㅎ.. 이렇게 보통 고차함수를 사용한다고 알고 있습니다.

map은 말 그대로 모든 요소들에 같은 연산이 필요한 경우 사용하는데, 위처럼 사용해서 forEach나 reduce같은 종다연산으로 마무리 짓는 편인 것 같습니다.(틀릴 수도 있어요. 자바는 Stream API라서 종단연산이 필수적인데, js는 그렇지는 않은 것 같아요.)

보통 저는 map filter를 많이 썼던 것 같습니다. 반복문에서 조건문이 들어가는 경우 map filter를 이용하면 간단해지는 경우가 많더라고요!

또 고차함수가 좋은 점은 별도의 저장할 배열을 따로 만들지 않아도 된다는 점도 있는 것 같아요.

글 잘 읽었습니다!!👍

답글 달기