자료형이란??
자료형이란, 값(value)의 종류이다.
자료형은 크게 두가지로 구분이 된다. 원시자료형, 참조 자료형이다.
let obj = {a=[4, 5, 6]}
위처럼 프로퍼티 명과 주소를 매치하기 위한 새로운 공간을 할당해보자.
이때, a 역시 객체이므로 a가 가르키는 주소에는 각 배열의 원소가 지정될 메모리 주소의 매치 정보가 저장되게 되고, 배열의 값은 각각의 주소에 따로 저장된다.
그렇다면 obj.a = 'new'와 같은 값 할당이 일어나면 어떻게 될까?
a가 가르키는 주소에는 'new'라는 데이터 값이 저장될 것이다. 이때, 각 원소들이 저장되어 있던 메모리 공간은 링크를 잃게 되어 galbage collerctor라고 하는 메모리 청소기의 청소 대상이 되어 삭제되게 된다.
let a;
a= 10;
let b = 'abc'
b= false;
let c = b;
c=20;
위의 코드는 아래와 같이 정리를 할 수 있다.
따라서, 원시 자료형과, 참조 자료형을 정리해보면
배열을 복사하는 방법은 크게 두 가지 방법이 있습니다. 배열 내장 메서드인 slice()를 사용하는 방법과 ES6에서 도입된 spread문법을 사용하는 방법입니다.
let arr = [0, 1, 2, 3];
let copiedArr = arr.slice();
console.log(copiedArr); // [0, 1, 2, 3]
console.log(arr === copiedArr); // false
새롭게 생성된 copiedArr 배열은 원본 배열과 같은 요소를 갖지만, 참조하고 있는 주소가 다르다.
copiedArr.push(4);
console.log(copiedArr); // [0, 1, 2, 3, 4]
console.log(arr); // [0, 1, 2, 3]
주소가 다르기 때문에 복사한 배열에 요소를 추가해도 원본배열에는 추가되지 않는다.
let arr = [0, 1, 2, 3];
console.log(...arr); // 0 1 2 3
그렇다면 새로운 배열 안에 원본 배열을 펼쳐서 전달하면 어떻게 될까요? 원본 배열과 같은 요소를 가지고 있지만 각각 다른 주소를 참조하게 됩니다. 결과적으로 slice() 메서드를 사용한 것과 동일하게 동작합니다.
let arr = [0, 1, 2, 3];
let copiedArr = [...arr];
console.log(copiedArr); // [0, 1, 2, 3]
console.log(arr === copiedArr); // false
copiedArr.push(4);
console.log(copiedArr); // [0, 1, 2, 3, 4]
console.log(arr); // [0, 1, 2, 3]
let obj = { firstName: "coding", lastName: "kim" };
let copiedObj = Object.assign({}, obj);
console.log(copiedObj) // { firstName: "coding", lastName: "kim" }
console.log(obj === copiedObj) // false
let obj = { firstName: "coding", lastName: "kim" };
let copiedObj = {...obj};
console.log(copiedObj) // { firstName: "coding", lastName: "kim" }
console.log(obj === copiedObj) // false
이처럼 slice(), Object.assign(), spread syntax 등의 방법으로 참조 자료형을 복사하면, 중첩된 구조 중 한 단계까지만 복사합니다. 이것을 얕은 복사(shallow copy)라고 합니다.
반면, 참조 자료형 내부에 중첩되어 있는 모든 참조 자료형을 복사하는 것은 깊은 복사(deep copy)라고 합니다. 그러나 JavaScript 내부적으로는 깊은 복사를 수행할 수 있는 방법이 없습니다. 단, JavaScript의 다른 문법을 응용하면 깊은 복사와 같은 결과물을 만들어 낼 수 있습니다.
const arr = [1, 2, [3, 4]];
const copiedArr = JSON.parse(JSON.stringify(arr));
console.log(arr); // [1, 2, [3, 4]]
console.log(copiedArr); // [1, 2, [3, 4]]
console.log(arr === copiedArr) // false
console.log(arr[2] === copiedArr[2]) // false
const lodash = require('lodash');
const arr = [1, 2, [3, 4]];
const copiedArr = lodash.cloneDeep(arr);
console.log(arr); // [1, 2, [3, 4]]
console.log(copiedArr); // [1, 2, [3, 4]]
console.log(arr === copiedArr) // false
console.log(arr[2] === copiedArr[2]) // false
배열복사를 정리해보자면,