Javascript에서 ['10','10','10'].map(parseInt) 가 [1,NaN,3]인 이유

도깨비젤리

·

2021. 8. 18. 00:30

파도파도 괴담만 나오는 Javascript

TL;DR


🦄자바스크립트가 너무 관대해서 벌어진 일이다.🦄
🦄매개변수를 받는 함수에 아무런 값도 넣어주지 않으면, JS는 자동으로 매개변수를 넣어준다🦄

 

 

 

본문


map이 뭐하는 함수인지도, parseInt가 뭐하는 함수인지도 다 알고 있겠지만, 그래도 다시 한번 하나 씩 살펴봅시다.

 

map은 배열 내의 모든 요소에 대하여 주어진 함수를 호출한 후, 그 결과를 모아 새로운 배열을 만드는 메서드이다

 

parseInt는 문자열 인자를 숫자로 반환하는 함수이다.

 

 

이 정도야 기본 중의 기본이지만, 그럼 혹시 map의 3번째 매개변수는 무엇인지 아는가?? 아니면 parseInt의 2번째 매개변수에 대해서는 아시나요??

 

잘 몰라도 괜찮다. 애초에 이 수수께끼가 그것들 때문에 생긴건 아니니까요

 

그래도 한번 공식 문서를 보고 갑시다

 

 

MDN 문서에 따르면, map의 callback 함수는 3가지 인수를 받는데, 첫번째가 현재 요소, 두번째가 현재 요소의 인덱스

세번째가 map을 호출한 배열이다.

 

아니 이게 무슨 상관이냐고?? 다음 코드를 실행해보자

 

[1, 2, 3, 4, 5].map(console.log);

 

그럼 위와 같은 결과가 나올 것이다. 근데 이 결과, 어디서 많이 본 거 같지 않나요??

 

맞습니다. map의 콜백 함수에 들어가는 인수들이 그대로 console.log에 의해 찍힌 것입니다.

 

신기하지 않나요?? 난 분명 아무런 값을 주지 않았는데 이렇게 콜백 함수들의 인수가 드르륵 나오다니...

 

상냥하게도 자바스크립트가 매개변수를 넣는 걸 잊은 개발자를 위해 남 몰래 인수를 넣어준겁니다.

 

그리고 그 괜한 짓 때문에 저는 이 글을 쓰게 되었습니다.

 

 

보다시피, 자바스크립트는 사용자가 콜백함수의 인수를 생략한다면, 본인이 알아서 인수를 집어넣어줍니다. 위 예시에서는 콜백 함수로 console.log가 왔는데, 만약 parseInt가 있다면 어떻게 될까요??

 

그 답을 구하기 전에 먼저 MDN 문서부터 봅시다.

 

 

 

parseInt는 2번째 인수로 radix라는 것을 받는데, 해당 문자를 몇진수로 표기할지를 알려주는 인수입니다.

 

근데 잠깐, 아까 위의 코드를 다시 봅시다.

 

지금 각 요소에 대해서 모종의 숫자들이 나오는데, 만약 console.log 자리에 parseInt가 들어가면 이렇게 되지 않을까요?

 

[1,2,3,4,5].map(parseInt)

// 첫번째 시행 element: 1
// map의 결과로 1,0,[1,2,3,4,5]가 parseInt에 전달
// -->  parseInt(1,0,[1,2,3,4,5]) 실행 ([1,2,3,4,5]는 parseInt가 3번째 인수를 받을 수 없기에 버려짐 )
// 0은 falsy 한 값이므로, 2번째 인수인 radix는 false가 되어 기본 값이 된다.
// 결국 parseInt(1)이 된다
// 결과 : 1

 

정확합니다. 다른 언어였다면, parseInt에 3번째 인수를 넣으려는 그 순간 에러를 불 같이 뿜었을텐데, 우리 착한 자바스크립트는 끝까지 개발자를 믿고 어떻게든 결과를 내오려고 합니다. 눈물이 앞을 가립니다 정말

 

 

대충 일이 어떻게 돌아가는지 알았으니, 본제로 돌아가봅시다.

 

["10,"10","10"].map(parseInt)의 결과가 왜 [1,NaN,3] 일까요???

 

 

['10', '10', '10'].map(parseInt);       // => [10, NaN, 2]

// 첫번째 순회 : val = "10" , index =0, array = ['10','10','10']
// 0 == false ==> redix = false ==> defalut 값인 10으로 적용
parseInt("10",0,['10','10','10']) => 10

// 두번째 순회 : val = "10" , index= 1 , array =['10','10','10']
// redix = 1 ==> 1진법에서는 "10"을 표기할 수 없음. 그렇기 때문에 NaN 반환
parseInt("10",1,['10','10','10']) => NaN

// 세번째 순회 : val = "10" , index= 2 , array =['10','10','10']
// redix = 2 ==> 2진법으로는 "10"은 3임
parseInt("10",2,['10','10','10']) => 3


// 따라서 map의 결과 [10,NaN,3]

 

 

이러한 이유 때문인데, 참 알면 알수록 복잡한 언어다...

 

 

레퍼런스


https://medium.com/dailyjs/parseint-mystery-7c4368ef7b21