728x90

메일로 한 통의 미디엄 글을 받았습니다. 해당 글의 경우 parseIntmap에 전달했을 때 이상한 값이 나온다는 내용이었는데 코드는 다음과 같습니다.

['1', '7', '11'].map(parseInt); // [1, NaN, 3]
['1', '7', '11'].map(Number); // [1, 7, 11]

위와 같이 나오는 이유에 대한 글인데, parseIntNumber의 매개변수는 각각 다음과 같습니다.

  • parseInt: string, radix
  • Number: value

Number에서는 잘 동작하지만 parseInt에서는 값의 결과가 깨지는 이유는 array.map의 콜백으로 parseInt를 사용하는 것이 함수 설계에 맞지 않기 때문입니다.

무엇이 문제일까?

const numList = ['1', '7', '11'].map(parseInt);

위 코드는 흔히 아래와 같다고 생각할 수 있습니다.

const numList = ['1', '7', '11'].map(item => parseInt(item));

하지만, 실제로는 아래 코드의 형태로 넘어갑니다.

const numList = ['1', '7', '11'].map((item, idx, arr) => parseInt(item, idx, arr));

배열 요소의 인덱스 값과 다루고 있는 배열을 parseInt 함수에 전달하는데, parseInt 함수의 경우에는 두 번째 인자로 몇진수로 표현할지에 대해서 2와 36 사이의 진수를 입력받기 떄문에 의도하지 않은 결과가 나오는 것입니다.

그렇다면 어떻게 해야할까?

parseInt 함수는 map을 위해 설계된 함수가 아닙니다. 진수 조정 등의 이유로 parseInt를 사용해야 한다면 아래와 같이 작성할 수 있을 것입니다.

const numList = ['1', '7', '11'].map(item => parseInt(item, 10));

단순히 위와 같이 작성하면 되며, 이제 의도하지 않은 결괏값이 나오는 것을 걱정하지 않아도 됩니다.

에러는 나지 않지만..

requestAnimationFrame()은 callback을 전달받습니다. 그리고 Promise 내에 requestAnimationFrame를 전달하는 경우가 종종 있습니다.

const promise = new Promise(requestAnimationFrame);

promise.then(function frameCallback(timestamp) => {
  // ... frame code
});

Promiseresolve, reject를 인자로 갖고 있는 함수를 전달받으며, 위 코드에서는 requestAnimationFramecallbackPromiseresolve에 대응한다고 볼 수 있습니다.

하지만, requestAnimationFrame 함수 역시 Promise를 위해 설계된 함수가 아니며, 파라미터가 추가될 경우 Promise에서 정상적으로 동작할 것이라고 보장할 수 없습니다. 많은 사용자가 위와 같은 방식으로 사용한다면 기존 코드에 영향을 주는 방향으로 업데이트가 될 가능성은 적겠지만, 그 확률이 0이라고는 할 수 없습니다.

결론

함수를 콜백으로 전달할 때 해당 콜백으로 동작하는 것을 고려하지 않은 함수라면 의도하지 않은 결과를 낼 수 있습니다. 그렇기에 함수를 콜백으로 전달할 때에는 주의가 필요합니다.

 

 

728x90
728x90