코딩쌀롱
new Array(3).fill([ ]) 문제 본문
문제 발생
[코드스쿼드 마스터즈 문제 - 3단계. 루빅스 큐브 구현]
큐브의 완전한 면을 3x3의 2차원 배열로 먼저 만들기 위해 arr1의 방식으로 6면을 만들었다.
그리고 큐브를 돌린 후 결과값을 다시 넣어줄 때 forEach 반복문을 돌리는데.. 문제가 발생했다.
3x3배열에서 오른쪽 열 값들을 바꾸기 위해 위의 forEach식을 사용했다.(오른쪽열이건 왼쪽열이건 똑같은 문제 발생함)
내가 예상했던 실행 과정
forEach 1번째 실행 | [['O', 'O', 1], ['O', 'O', 'O'], ['O', 'O', 'O']] |
forEach 2번째 실행 | [['O', 'O', 1], ['O', 'O', 2], ['O', 'O', 'O']] |
forEach 3번째 실행 | [['O', 'O', 1], ['O', 'O', 2], ['O', 'O', 3]] |
실제 실행 과정(디버깅)
forEach 1번째 실행 | [['O', 'O', 1], ['O', 'O', 1], ['O', 'O', 1]] |
forEach 2번째 실행 | [['O', 'O', 2], ['O', 'O', 2], ['O', 'O', 2]] |
forEach 3번째 실행 | [['O', 'O', 3], ['O', 'O', 3], ['O', 'O', 3]] |
한 번 실행할 때마다 안에 있는 배열들이 마치 같은 배열의 원소인냥 한 번에 같이 값이 바뀌었다.
결과값으로 2차원 배열의 오른쪽 열이 1, 2, 3이 아니라 3, 3, 3으로 나왔다.
문제 원인
문제는 fill()메서드의 인자에 있었다.
arr.fill(value[, start[, end]])
fill()메서드는 배열의 시작 인덱스부터 끝 인덱스의 이전까지 정적인 값 하나로 채운다.
매개변수 value는 배열을 채울 값, start는 시작 인덱스, end는 끝 인덱스이고, 변형한 배열을 반환한다.
중요한 것은, value에 객체를 받을 경우 그 참조만 복사해서 배열을 채운다는 것.
// Objects by reference.
var arr = Array(3).fill({}); // [{}, {}, {}]
arr[0].hi = "hi"; // [{hi: "hi"}, {hi: "hi"}, {hi: "hi"}]
필수 매개변수인 value에 어떤 데이터 타입이 들어가는지에 따라 매우 달라진다.
참조형 데이터를 넣을 경우에는 참조를 복사하기 때문에 결국 주소값이 같은 참조형 데이터로 배열이 채워진다. 따라서 배열의 한 원소만 바꾸려고 해도 모든 원소들이 같이 바뀐다. 내 코드를 다시 보면,
const arr = new Array(3).fill(new Array(3).fill('O'));
안쪽의 fill 메서드 안에는 문자열인 정적인 값을 넣었지만, 바깥의 fill 메서드 안에 배열(['O', 'O', 'O'])을 넣었다. 그렇기 때문에 forEach로 내부 배열의 값을 하나씩 변경할 때 모든 원소들이 같이 값이 바뀌었던 것이다.(같은 주소값)
해결 방법
제일 위의 사진에서 arr2처럼 배열리터럴로 직접 만들었다.
생각치도 못한 곳에서 문제가 발생했고, 문제 원인을 알아내는 데에도 시간이 꽤 걸렸다. 문제를 해결하는 것은 매우 간단했지만 문제 원인을 정확히 이해하는 것이 중요했던 것 같다.
'개발공부' 카테고리의 다른 글
[프로그래머스_JS] 영어 끝말 잇기 (0) | 2020.12.22 |
---|---|
push()의 반환값 (0) | 2020.12.21 |
[프로그래머스_JS] 멀쩡한 사각형 (0) | 2020.12.18 |
Algorithm Day(배열 최소값 찾기, 문자열 자르기) (0) | 2020.12.16 |