자바 스크립트, 자바를 처음 배우면서 이미 배우는 개념들이 어렵다는 이유로 '지금 말고 나중에!'를 외치며 외면하다가 결국 만나버렸다. 피한다고 되는 일 하나 없다는 교훈... 그래두 배열 어려워잉...
Array.prototype.map() 공식 문서를 보면서 배운 것도 있고, 실제 코드를 보면서 배운 것들을 정리해보려고 한다. 비공식..? 공식..? 애매하지만 나의 사수인,,, 데(devOps^0^)정현님께 감사⭐
map()
배열 내의 모든 요소 각각에 대하여 주어진 함수를 호출한 결과를 모아 새로운 배열을 반환한다
arr.map(callback(currentValue[, index[, array]])[, thisArg])
callback
map()
메서드는 콜백함수를 통해 새로운 배열을 생성하며 다음과 같은 세 가지 인수를 갖는다currentValue
: 처리할 현재 요소 index
: 처리할 현재 요소의 인덱스 (optional)array
: map()
을 호출한 배열 (optional)thisArg
: 콜백함수를 실행할 때 this
로 사용되는 값 (optional)반환값
→ 배열의 각 요소에 대해 실행한 콜백함수의 결과를 모은 새로운 배열
callback
함수를 각각의 요소에 대해 한번씩 순서대로 불러 그 함수의 반환값으로 새로운 배열을 만든다
callback
함수는 (undefined
포함) 배열 값이 들어있는 인덱스에 대해서만 호출
→ 삭제된 값이나 아직 값이 할당/정의되지 않은 인덱스에 대해서는 호출되지 않는다
map
을 호출한 원래 배열의 요소를 순서대로 하나씩 callback
함수에 넣어서 나오는 반환값으로 새로운 배열을 만든다는 의미!!
원본 배열에서 map
을 호출하게 되면 인덱스 0번 부터 값을 하나하나 꺼내와서 콜백함수를 실행시키고 그 반환값들을 통해서 새로운 배열을 만드는 것이다.
callback
함수는 호출될 때 대상 요소의 값, 그 요소의 인덱스, 그리고map
을 호출한 원본 배열 3개의 인수를 전달받는다
thisArg
매개변수가map
에 전달된 경우callback
함수의this
값으로 사용된다- 그 외의 경우
undefined
값이this
로 사용된다callback
함수에서 최종적으로 볼 수 있는this
값은 함수 내this
를 정하는 일반적인 규칙에 따라 결정된다
음... 여긴 뭔 소린지 잘 모르겠다... 어떻게 쓰인다는 건지...? 감이 잘 안 잡힌다.
map
은 호출한 배열의 값을 변형하지 않는다
- 단,
callback
함수에 의해서 변형될 수는 있다
→ 배열 값은 그대로 가져오면서 값을 추가하거나 콜백함수의 로직에 따라서 내용을 변형할 수 있다(는 이야기 같음)
map
이 처리할 요소의 범위는 첫callback
을 호출하기 전에 정해진다
map
이 시작한 이후 배열에 추가되는 요소들은callback
을 호출하지 않는다- 배열에 존재하는 요소들의 값이 바뀐 경우
map
이 방문하는 시점의 값이callback
에 전달된다map
이 시작되고, 방문하기 전에 삭제된 요소들은 방문하지 않는다
- 명세서에 정의된 알고리즘으로 인해
map
을 호출한 배열의 중간이 비어있는 경우, 결과 배열 또한 동일한 인덱스를 빈 값으로 유지한다
var kvArray = [
{ key: 1, value: 10 },
{ key: 2, value: 20 },
{ key: 3, value: 30 },
];
var reformattedArray = kvArray.map(function (obj) {
var rObj = {};
rObj[obj.key] = obj.value;
return rObj;
});
// reformattedArray는 [{1:10}, {2:20}, {3:30}]
// kvArray는 그대로
// [{key:1, value:10},
// {key:2, value:20},
// {key:3, value: 30}]
kvArray
라는 배열은 key
-value
값으로 이루어진 객체를 담고 있다. (객체 배열)
map
을 호출하여 콜백함수를 실행하는데
rObj
라는 빈 객체를 선언하고
그 안에 obj
로 호출한 kvArray
의 key
값을 하나씩 호출하여 value
를 할당한다. (원본 배열의key
값이 속성이 되고 value
가 값이 된는 것)
kvArray
의 첫 번째 인덱스부터 이를 반복하여 rObj
에 넣어준 후 이를 반환한다. 객체를 약간 변형하여 새로 저장!!
var numbers = [1, 4, 9];
var doubles = numbers.map(function (num) {
return num * 2;
});
// doubles는 이제 [2, 8, 18]
// numbers는 그대로 [1, 4, 9]
numbers
라는 배열에서 map
을 호출한 뒤 num
으로 불러온 numbers
배열의 값을 두 배하여 반환한다.
map
은 대충 이렇게 쓰인다... 정도로 정리... 복잡한 for
문을 쓰지 않고 배열을 새로 정의하는 방법에 관한 함수인 것 같다.
공식 문서가 약간 이해가 되지 않아서 보충할 수 있는 다른 내용을 찾아봤다.
map()
메소드 구문
arr.map(function(element, index, array) { }, this);
→ 콜백함수는 각 배열 요소에 대해서 호출된다
→ map()
메소드는 언제나 현재의 element
와 그것의 index
, 전체 array
객체를 해당 요소에 전달한다. (index, array는 옵셔널한 값)
→ this
는 콜백함수 내부에서 사용된다. 기본적으로는 undefined
이지만 다른 값으로 변경할 수도 있다.
let arr = [2, 3, 5, 7]
arr.map(function(element, index, array){
console.log(this) // 80
}, 80);
this
인수에 숫자 값을 할당했다.
보통은 콜백 함수 내부의 element
인수만 사용한다.
실제 내가 어떻게 map()
메서드를 사용했는지에 대한 예시이다.
const noticeInfo: Notice[] = await Notice.findAll({
where: { mainCategory: '공지사항' },
});
const getNoticeInfo = noticeInfo.map((item) => {
return {
id: item.id,
title: item.title,
mainCategory: item.mainCategory,
fullDate: item.updatedAt.toISOString().split('T')[0],
};
});
noticeInfo
라는 배열을 선언한 후, Notice
테이블에서 mainCategory가 '공지사항'인 요소들을 불러온다.
이 배열에 fullDate
라는 요소를 추가해야 하기 때문에 map
을 호출하였다.
item
으로 요소를 하나씩 호출하여 객체를 새로 반환할 것이다.
내가 필요한 것은 id
와 title
, mainCategory
, 그리고 새롭게 추가할 fullDate
라는 값이다. 그래서 ...item
으로 모든 값을 불러오지 않고 하나씩 뽑아서 가져올 것이다. ...item
으로 원본 배열의 모든 것을 호출하면 깔끔하게 안 찍히는 것 같은 너낌...
그래서 getNoticeInfo
에는 id값을 원본 배열에서 뽑아온 id 값을 넣어주고, title과 mainCategory에도 반복하여 item으로 원본 배열에서 뽑아온 값들을 넣어준다.
fullDate
는 'YYYY-MM-DD' 형식의 날짜 데이터를 'string' 타입으로 가져와야 한다. 떄문에 원본 배열에서 updatedAt을 뽑아온 후 toISOSting()
이라는 함수로 Date 타입을 내가 원하는 포맷으로 뽑아온다.
Date.prototype.toISOString()
toISOString() 메서드는 단순화한 확장 ISO 형식(ISO 8601)의 문자열을 반환합니다. 반환값은 언제나 24글자 또는 27글자(각각 YYYY-MM-DDTHH:mm:ss.sssZ 또는 ±YYYYYY-MM-DDTHH:mm:ss.sssZ)입니다.시간대는 언제나 UTC이며 접미어 Z로 표현합니다.나는 년-월-일의 형식으로 된 스트링 데이터 변환이 필요한데 단순히
toDateString()
이라는 함수를 통해 변환하니까Wed Oct 05 2011 16:48:00 GMT+0200 (CEST)
이런 형식으로 반환이 되어서 찾아 본 함수이다.toISOString()
을 하면2011-10-05T14:48:00.000Z
이런 형식으로 날짜 데이터를 문자열로 받을 수 있다.
하지만 내가 필요한 것은 날짜 부분의 데이터이기 때문에 split()
을 통해서 'T'를 기준으로 잘라준 후 0번째 인덱스인 앞부분 날짜 데이터만 가져와 fullDate
라는 값에 넣어준다.
그렇게 내가 필요한 문자열의 날짜 값 fullDate
를 포함한 새로운 배열을 만들었다!
거의 다 떠먹여주신 내용... 감사해요 데정현 🤩 !