모르는 것으로 빠지는 JavaScript의 배열 복사

개요



JavaScript로 배열 복사를 할 때,
「=(이콜)」에 의한 카피에서는 의도한 동작이 되지 않는 경우가 있습니다.
의외로 빠지기 쉬운 함정이라고 생각했기 때문에,
초보자도 알기 쉽도록 그림도 올려 놓았습니다.

배열 복사에 의한 움직임



우선, 움직임을 확인합시다.

변수 a의 배열을 선언하고 변수 b에 복사합니다.

test.js
var a = ['','','','',''];
var b = a;

그런 다음 변수 b[0]의 내용을 다시 씁니다.

test.js
b[0] = '';

이때 다시 쓰고 싶은 것은 변수 b의 값이지만 실제로는

test.js
  console.log('変数a: ' + a); // ['か','い','う','え','お']
  console.log('変数b: ' + b); // ['か','い','う','え','お']

그리고 변수 a의 값도 다시 쓰여집니다.
다시 쓴 것은 변수 b였는데, 왜 변수 a도 함께 다시 쓰여져 버렸습니까?

복사 원본 값이 다시 작성되는 이유



그렇다면 왜 변수 b의 값을 다시 쓰더라도 변수 a의 값도 다시 쓰여졌습니까?
그림을 섞어 설명하겠습니다.

첫째, 이 변수 ​​a에 저장된 값은 배열 정보가 아니라,
배열 a의 인스턴스를 참조하는 주소를 저장합니다.

따라서 변수 b에 변수 a를 복사 할 때,
배열이 아닌 주소 정보가 전달되고 있습니다.

실제로 그림으로 하면 다음 상태입니다.


다음으로, 변수 b[0]에 「인가」라는 문자를 대입했습니다만,
이때 변수 b[0]은 변수 b의 값을 다시 쓰는 것이 아니라,
배열의 값을 보관 유지한 메모리를 직접 재기록하게 됩니다.



즉,이 b = a라는 식에서 배열은 복제되지 않습니다.
같은 주소처를 공유하고 있을 뿐입니다.

이 동작을 이해하지 못하면,
마치 두 변수에서 값이 다시 쓰여진 것처럼 느껴집니다.

배열을 복제하는 방법



그렇다면 실제로 배열을 복제하려면 어떻게해야할지 몇 가지 예를 들어 둡니다.
※상기의 설명으로 카피라는 표현이 적절하지 않다고 알았으므로, 여기에서는 「복제」라고 하는 표현으로 바꿉니다

for 문으로 복제



for문을 사용해, 배열 요소문의 루프에 의해 값을 대입합니다.
이 때 변수 b는 빈 배열로 선언합니다.

test.js
  var a = ['','','','',''];
  var b =[];

  for( var i =0; i < a.length; i++){
    b[i] = a[i];
  }

  b[0] = '';
  console.log('変数a: ' + a); // ['あ','い','う','え','お']
  console.log('変数b: ' + b); // ['か','い','う','え','お']

Array.concat()에 의한 복제



Array 객체의 concat 메서드는 지정된 배열을 연결하여 값을 반환하는 메서드이지만
인수를 지정하지 않는 경우는, 원의 배열의 복제를 돌려줍니다.

test.js
  var a = ['','','','',''];
  var b = a.concat();

  b[0] = '';
  console.log('変数a: ' + a); // ['あ','い','う','え','お']
  console.log('変数b: ' + b); // ['か','い','う','え','お']

Array.slice()로 복제



Array 객체의 slice 객체는 배열의 일부를 검색하고 값을 반환하는 메서드이지만,
시작을 지정하고 종료를 생략하면 원래 배열의 복제본을 반환합니다.

test.js
  var a = ['','','','',''];
  var b = a.slice(0);

  b[0] = '';
  console.log('変数a: ' + a); // ['あ','い','う','え','お']
  console.log('変数b: ' + b); // ['か','い','う','え','お']

... 연산자로 복제



ES6(ES2015)에서 추가된 스프레드 구문을 사용하면 배열을 그대로 복제할 수 있습니다.

그러나 ES6을 지원하는 브라우저만 지원됩니다.
※ 2020년 1월 시점에서는 IE11은 비지원입니다.

test.js
  var a = ['','','','',''];
  var b = [...a]

  b[0] = '';
  console.log('変数a: ' + a); // ['あ','い','う','え','お']
  console.log('変数b: ' + b); // ['か','い','う','え','お']

요약



"= (이콜)"을 사용하여 변수의 값을 복사 (대입) 할 때
그 변수가 어떤 값을 보유하고 있는지 주의합시다.

좋은 웹페이지 즐겨찾기