본문 바로가기
Product Development/Javascript

Array(n)에는 map()을 쓸 수 없다.

by Kyle Ausk 2023. 7. 14.

Array() Constructor로 생성한 배열 객체

Array() Constructor의 인자로 한개의 값만 넣어주면, length 프로퍼티를 가진 배열 객체가 하나 생성된다.
예를 들어 길이 5의 배열 객체를 생성하면 다음과 같다.

Array(5)

이제 5개의 빈 값(empty)들을 가지고 있는 이 배열 객체에, 모든 element를 숫자 5로 채워넣고자 map을 실행하면 어떻게 될까?

Array(5).map(() => 5)

우리는

[5, 5, 5, 5, 5]

와 같은 결과를 기대했지만 아쉽게도 이 배열의 형태는 전혀 변하지 않았다.

왜 그럴까?
그 이유는 Array.prototype.map이 배열의 "빈 값"은 건너뛰도록 설계되었기 때문이다. (이런 "빈 값"이 들어있는 배열을 Sparse Array 라고 한다.)

Function.prototype.apply() 사용하기

그렇다면 다시 처음으로 돌아가서, Array() Constructor를 사용해 새로 생성한 배열객체에, map()을 사용하고싶다면 어떻게 하면 될까?

그럴땐 apply()를 사용하면 된다.

Array.apply(null, Array(5))

짠! 이번에는 empty 가 아닌 undefined라는 "값"으로 채워진 배열이 생성되었다. 이제 여기에 map()을 사용해 모든 element를 숫자 5로 바꿔준다면?

Array.apply(null, Array(5)).map(() => 5)

이제서야 의도했던

[5, 5, 5, 5, 5]

라는 배열을 가질 수 있게 되었다!

이는 apply()가 가진 특성을 이용한 방법이다. apply()는 두번째 인자(argsArray)를 decompose하여 각각의 개별적인 인자로 바꾸어주는데, 여기에서 "빈 값(empty) "이 있다면 이를 자동으로 undefined로 치환해준다.
이는 마치 아래와 같은 방식으로 Array() Constructor를 실행해준 것과 같다.

Array(undefined, undefined, undefined, undefined, undefined)

따라서 각 undefinedmap()을 이용해 5 라는 값으로 바꿔주는 것이 가능했던 것이다.

Spread syntax 사용하기

대부분의 경우 apply 메소드는 parameter spread syntax와 동일한 역할을 하기 때문에 apply 대신 아래와 같은 코드를 작성할 수도 있다.

Array(...Array(5)).map(() => 5)

이 또한 동일하게 작동한다.

참고

처음 이 문제에 대한 해결책을 찾은 stackoverflow 글
은근히 유용했던 MDN apply문서