Array( ).fill( ) (TIL 39일차)

"해치우는 블로깅..."


Intro

여유를 찾게 된다면 새로 배우는 개념들을 꼭 블로깅하고 싶은데, 어제도 그렇지만 주어진 문제들을 아직 다 소화하지 못했습니다. 이번주도 주말은 없는 셈이네요 ㅠ_ㅠ

진도를 나가는 데 걸림돌이 되는 것들은, 의외로 기존의 알고 있다고 생각한 개념들을 제대로 사용하지 못 한 경우가 대부분이더라구요. 어제도 그렇고 오늘 블로깅할 주제도 사용법을 알고 있다고 생각했지만, 실제로 코드를 돌려보니 다른 방식으로 작동해서 한참을 막혔더랬습니다.

그런 김에 적어보는 오늘 TIL 의 주제는 바로바로, Array( ).fill( ) 의 사용 시 고려해야 하는 주의사항입니다.


Array( )

먼저 Array( ) 부터 살펴보도록 하겠습니다. mdn 공식문서에 잘 설명되어 있는데요. Array( ) 가 대문자로 시작한다는 점에서 유추할 수 있듯이, 클래스와 비슷하게 new 를 앞에 붙여 사용합니다.

let a = new Array(2).fill(false); // [false, false]

개발자 도구에 찍어보니 new 없이도 잘 작동하던데요? 네 맞습니다. 왜 가능한지가 궁금해 구글링을 좀 해봤는데 아직은 속 시원한 답을 얻지는 못했습니다. 공식 문서에서 new 를 이용하라고 되어있으니 가급적 그렇게 이용하는 것이 좋겠다고만 생각하고 있습니다..ㅋㅋ

특히 Array( ) 는 괄호 안에 요소를 하나만,그리고 숫자 자료형으로 넣어줄 경우 그 매개변수를 arrayLength 로 판단한다는 특징이 있습니다. 이렇게 생성된 배열은 undefined 가 아닌 빈 슬롯로 채워지게 되죠. 사용 가능한 매개변수 값의 범위는 "0에서부터 2^32 - 1 이하의 정수"라고 합니다.


.fill( )

앞에서 Array( ) 에 하나의 숫자를 단독으로 넣어주면 그 길이만큼의 빈 슬롯을 지니는 배열이 생성된다고 했는데요. 빈 슬롯을 방지하고 유의미한 값을 채우기 위해 사용되는 것이 바로 .fill( ) 메소드입니다.

.fill( ) 메소드 또한 매개변수에 Optional 한 값을 추가해 사용할 수 있지만, Array( ) 와 묶어 사용할 때는 종종 하나의 매개변수만을 지정합니다. 하나만을 지정할 경우 Array 전체를 해당하는 값으로 채우게 되죠.

let b = new Array(5).fill(0);  // [0, 0, 0, 0, 0]

시행착오

관련해 오늘 겪었던 시행착오 하나를 소개할까 합니다. 자료구조에 대해 배우다보니 2차원 배열을 다루게 되었습니다. 2차원 배열의 가장 쉬운 예는 excel 의 행렬인데요. 자바스크립트에서는 배열 내부의 배열을 만들어 2차원 배열을 구성할 수 있습니다.

const c = [
  [0, 0, 0],
  [0, 0, 0],
  [0, 0, 0],
];

3 * 3 으로 이루어진 2차원 배열을 만들 수 있습니다. 반복되는 부분이 있다는 건 반복을 이용해서 같은 배열을 만들 수 있다는 뜻이겠죠? 그래서 다음과 같이 반복문으로 배열을 만들어보았습니다.

const innerArr = new Array(3).fill(0);
const d = [];
for (let i = 0; i < 3; i++) {
  d.push(innerArr);
}

d[0][1] = 1; // 결과는??

외양적으로 c 와 d 는 동일한 모양을 가지고 있습니다. 하지만 위처럼 innerArr 이라는 변수에 배열 생성자 new Array( ) 를 할당하고 이를 반복해서 d 에 push 하게 되면, d 배열의 요소들인 내부 배열이 모두 innerArr 이 참조하는 배열로 구성된다는 문제를 가지게 됩니다.

따라서 d[0][1] 로 접근해 1이라는 숫자를 할당해줄 경우, 2차원 배열의 [1] 번째 세로열이 모두 1로 변하게 됩니다.

// [
// [0, 1, 0],
// [0, 1, 0],
// [0, 1, 0],
// ];

2차원 배열의 기능을 전혀 수행하지 못 하는 결과가 도출되었습니다. 이를 해결하려면 따로 변수에 할당하고 변수를 반복해주는 것이 아니라 반복문 안에서 자체적으로 new Array( ) 생성자를 반복해줘야 합니다. 바로 다음처럼 말이죠.

const e = [];
for (let i = 0; i < 3; i++) {
  e.push(new Array(3).fill(0));
}

e[0][1] = 1; // 결과는??

// [
// [0, 1, 0],
// [0, 0, 0],
// [0, 0, 0],
// ];

변수의 이름에 배열이 할당될 때, 주소를 참조하는 형태로 전달된다는 걸 알고 있는데도 이런 실수로 한참을 허비했습니다. 혹시라도 이 글을 보시는 분들은 같은 실수를 미연에 방지하실 수 있었으면 좋겠네요.

좋은 웹페이지 즐겨찾기