Map() 객체, .forEach(), spread 연산자 및 .flatmap() 사용법

함수형 프로그래밍의 특징을 단순히 머리로 아는 것과, 내가 실제로 함수형 프로그래밍 방식으로 코드를 짜는 것에는 큰 차이가 있다. 가장 적응이 되지 않는 부분은 데이터의 '상태'를 저장하지 않고, 일련의 함수를 통해 데이터 흐름을 유지하는 것이다.

자바스크립트에서는 함수형 프로그래밍 패러다임을 구현할 수 있는데, 프로그래머스 '베스트 앨범'[링크] 문제를 풀면서, 기존의 절차 지향적인 방법이 아닌 함수지향적 방식으로 코드를 짜는 법을 배우게 되었다. 그 과정에서 새로 알게 된 자바스크립트 문법과 객체 및 함수들을 조금 적어보려 한다. + 간단한 소감은 덤이다.^^

1. Map() collection 객체 set(), get() 매서드

Map()객체는 키값으로 정렬되는 데이터의 집합(자료구조)이며, 객체의 요소들은 반복적으로 접근할 수 있다. 나는 항상 기존에 알고 있는 지식과 새로운 지식을 비교하면서 공부하는 편이라, JavaScript를 공부할 때도 내가 그나마 잘 알고 있는 언어인 Python과 비교하며 공부하고 있다. 그런데 Map()이라는 녀석은 보아하니 key:value쌍을 저장한다는 점에서 Python의 딕셔너리와 유사해 보인다. 오케이 이해 완료.

JavaScript 내에서 Map() 객체는 Object객체와 매우 비슷해 보이지만 몇 가지 차이점이 있다.

먼저 객체에 값을 넣을 때, Map에서는 함수나 객체도 키값으로 넣을 수 있다고 한다. 반면 Object는 키값이 무조건 string이어야 한다.

그리고 잦은 키 값 입력과 출력에서는 Map()객체가 성능이 더 낫다고 한다. 그러니 Map()을 자주 쓰도록 하자!

또한 Map객체에선

No native support for serialization or parsing

이라는 점! JSON으로 바꿀 일이 있다면 Object를 사용토록 하자.

const map = new Map();
map.set("key1",3);
map.set("key2",[1,2,3,4]);
map[3] = "rokrok";
map.set(4,5)
map.set("key3",[1,2,3,4]);
console.log(map, map.size) //Map(4) {'key1' => 3,'key2' => [ 1, 2, 3, 4 ],4 => 5,'key3' => [ 1, 2, 3, 4 ], '3': 'rokrok' } 4

여기서 궁금증 하나! 객체의 요소는 분명히 5개인데 왜 size는 4인가?
Map()[key]= value; 할당은 set, get과는 차이가 있는 것 같다. 이에 대한 조사가 필요!

Map객체에 관하여 더 알고 싶다면 [요기]를 참조하세요!

2. 배열.forEach

.forEach에 관하여 더 알고 싶다면 [요기]에 ....있는 예시를 참고해서 .forEach를 이해해보자!

const items = ['item1', 'item2', 'item3'];
const copy = [];

// 이전
for (let i=0; i<items.length; i++) {
  copy.push(items[i]);
}

// 이후
items.forEach(function(item){
  copy.push(item);
});

흠흠 아래처럼 쓰니까 가독성이 훨씬 좋아진 것이 보인다. 흐름제어 구문을 사용하는 대신에 forEach라는 함수로 퉁치는 느낌이다. 아래 forEach함수 내부에 있는 함수는 callback함수라는 것인데, 또 이러면 이해가 한번에 가지 않는다.

내가 이해하기로 콜백함수는 저렇게 함수 내부에 인자로 정의된 함수인데, 저러면 forEach라는 함수가 실행되었을때만 실행되고 그 안에서 끝이난다.

오호라...그러면 저 function(item)에서 인자 item 은 forEach가 items에서 요소 하나하나를 뽑으면, 그 뽑아낸 녀석을 item삼아서 copy배열에 push를 하는 함수로구나!

이렇게 코드를 쓰면 좋은점이 내 말로 표현하자면 '직독직해'가 가능하다는 점이다. 그냥 왼쪽에서 오른쪽으로 읽으면서 '그렇네'하고 끝이 난단말이다.

콜백함수의 정의는 [요기]를 읽으니 좀 알 것 같다.

3. ... ?

이 연산자는 내가 태어나서 처음 본 연산자이다. 처음 이 연산자를 보았을 때 마음속으로 ... 연산자를 "어쩌구저쩌구"라고 읽었는데, 기능도 이와 비슷해서 재미있었다. 이름은 spread 연산자이며, 이름 그대로, iterable한 객체의 요소를 하나씩 전개한다.

그래서 배열과 자주 쓰일 것 같다는 느낌이 든다. 왜냐면 원래 iterable한 객체들의 요소를 하나씩 떼어주려면 for 문으로 하나씩 접근해야 하는데, 이 연산자가 있으면 엄청 간단하게 한 줄로!!! 각 요소들을 배열에 저장 할 수 있기 때문.

console.log([..."starcraft"]) // ['s','t','a','r','c','r','a','f','t']

4. 배열.flatMap(), .map()

배열 안에 들어있는 string들의 일괄처리 시에 굉장히 유용해 보인다! 역시 예시 코드 출처는 [요기]

let arr1 = ["it's Sunny in", "", "California"];

arr1.map(x=>x.split(" "));
// [["it's","Sunny","in"],[""],["California"]]

arr1.flatMap(x => x.split(" "));
// ["it's","Sunny","in","California"]

와... 나였으면 for문을 써서 각 string마다 split하고 for문써서 return된 배열을 다시 배열에 넣는 작업을 했을텐데...

VS code로 여러 인풋을 가지고 연습해 봐야겠다.

5. 오늘 느낀 점

  • Map과 Object 객체는 서로 비슷한 면도 있지만, 다른 점도 있었다. 특히 JSON 파싱이 네이티브로 지원이 안된다는 것은 치명적인 차이같다. 흠흠...!

  • 객체가 지원하는 매서드를 잘 알면, 길어질 코딩도 짧아진다는 점! 좀 더 가독성도 좋아지겠지요?

  • TIL을 하면서 좋은 점은, 매일의 내 성장을 가시적으로 확인할 수 있다는 점이다. TIL에는 항상 내가 새로 깨닫고 알게 된 내용이 적히니 말이다. 아 물론, 새로 알고 나서 까먹을 수도 있기 때문에 꾸준히 복습도 해 주어야겠다.

  • 그리고 마지막으로, 내 성장의 기록들이 혹시라도 이 글을 발견할 미래의 누군가에게 조금이라도 도움이 되기를 간절히 소망한다. 지금까지 내가 다른 사람들이 기록한 무언가를 보고 공부하고, 성장하고, 깨달았듯이 말이다. 그래서 나는 TIL을 대충 작성할 수가 없는 것 같다. 그래서 욕심이 생겨 자꾸 밀리는 것 같기도 하고...?ㅎㅎ

profile
안녕하세요 개발자 윤승록입니다. 내 성장을 가시적으로 기록하기 위해 블로그를 운영중입니다.

6개의 댓글

comment-user-thumbnail
2021년 8월 9일

갓승록.. 그는 대체...🤩.. 진짜 정말 빠듯한 기간인데 멋진 아티클이십니다!
많이 배우고 갑니다ㅎㅎㅎ

3개의 답글
comment-user-thumbnail
2021년 8월 9일

오오... 승더갓록디그다님... 아티클... 좋아요..!

1개의 답글