함수형 프로그래밍의 특징을 단순히 머리로 아는 것과, 내가 실제로 함수형 프로그래밍 방식으로 코드를 짜는 것에는 큰 차이가 있다. 가장 적응이 되지 않는 부분은 데이터의 '상태'를 저장하지 않고, 일련의 함수를 통해 데이터 흐름을 유지하는 것이다.
자바스크립트에서는 함수형 프로그래밍 패러다임을 구현할 수 있는데, 프로그래머스 '베스트 앨범'[링크] 문제를 풀면서, 기존의 절차 지향적인 방법이 아닌 함수지향적 방식으로 코드를 짜는 법을 배우게 되었다. 그 과정에서 새로 알게 된 자바스크립트 문법과 객체 및 함수들을 조금 적어보려 한다. + 간단한 소감은 덤이다.^^
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객체에 관하여 더 알고 싶다면 [요기]를 참조하세요!
.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를 하는 함수로구나!
이렇게 코드를 쓰면 좋은점이 내 말로 표현하자면 '직독직해'가 가능하다는 점이다. 그냥 왼쪽에서 오른쪽으로 읽으면서 '그렇네'하고 끝이 난단말이다.
콜백함수의 정의는 [요기]를 읽으니 좀 알 것 같다.
이 연산자는 내가 태어나서 처음 본 연산자이다. 처음 이 연산자를 보았을 때 마음속으로 ... 연산자를 "어쩌구저쩌구"라고 읽었는데, 기능도 이와 비슷해서 재미있었다. 이름은 spread 연산자이며, 이름 그대로, iterable한 객체의 요소를 하나씩 전개한다.
그래서 배열과 자주 쓰일 것 같다는 느낌이 든다. 왜냐면 원래 iterable한 객체들의 요소를 하나씩 떼어주려면 for 문으로 하나씩 접근해야 하는데, 이 연산자가 있으면 엄청 간단하게 한 줄로!!! 각 요소들을 배열에 저장 할 수 있기 때문.
console.log([..."starcraft"]) // ['s','t','a','r','c','r','a','f','t']
배열 안에 들어있는 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로 여러 인풋을 가지고 연습해 봐야겠다.
Map과 Object 객체는 서로 비슷한 면도 있지만, 다른 점도 있었다. 특히 JSON 파싱이 네이티브로 지원이 안된다는 것은 치명적인 차이같다. 흠흠...!
객체가 지원하는 매서드를 잘 알면, 길어질 코딩도 짧아진다는 점! 좀 더 가독성도 좋아지겠지요?
TIL을 하면서 좋은 점은, 매일의 내 성장을 가시적으로 확인할 수 있다는 점이다. TIL에는 항상 내가 새로 깨닫고 알게 된 내용이 적히니 말이다. 아 물론, 새로 알고 나서 까먹을 수도 있기 때문에 꾸준히 복습도 해 주어야겠다.
그리고 마지막으로, 내 성장의 기록들이 혹시라도 이 글을 발견할 미래의 누군가에게 조금이라도 도움이 되기를 간절히 소망한다. 지금까지 내가 다른 사람들이 기록한 무언가를 보고 공부하고, 성장하고, 깨달았듯이 말이다. 그래서 나는 TIL을 대충 작성할 수가 없는 것 같다. 그래서 욕심이 생겨 자꾸 밀리는 것 같기도 하고...?ㅎㅎ
갓승록.. 그는 대체...🤩.. 진짜 정말 빠듯한 기간인데 멋진 아티클이십니다!
많이 배우고 갑니다ㅎㅎㅎ