할당이나 연산할 때 값을 복사하면 기본형이고, 주소를 복사하면 참조형이다.
기존 값의 주소가 같이 복사되는 것이 아니라 내용만 빼와서 복사된다. 깊은 복사된 값이 변경되어도 기존 값은 변경되지 않는다.
var a = 5;
var b = 5;
console.log(a === b); // true
var c = 10;
var d = c; // d === 10
console.log(c === d); // true
d = 5; // c로부터 가져온 값을 변경해 줘 보았다.
console.log(c); // 10으로 c의 값은 변하지 않았다.
console.log(d); // 5
console.log(c === d); // false
기본형 타입의 깊은 복사는 값이 변경될 때, 서로에게 영향을 주지 않았다.
이게 바로 깊은 복사이다.
기존 값의 주소를 같이 복사해온다. 얕은 복사된 값이 변경되면 기존 값도 같이 변경된다.
let obj1 = { name: "mingming" };
let obj2 = obj1;
console.log(obj1); // {name: 'mingming'}
console.log(obj2); // {name: 'mingming'}
console.log(obj1 === obj2); // true
obj2.age = { age: 24 };
console.log(obj1); // {name: 'mingming', age:24}
console.log(obj2); // {name: 'mingming', age:24}
console.log(obj1 === obj2); // true
분명 obj2 객체에 age를 추가해주었는데,
obj1 객체 역시 age가 추가된 것을 확인할 수 있다.
참조형은 주소를 복사해 공유하기 때문에 서로에게 영향을 준다.
👉🏻 참고 블로그 바로가기
기본형과 같이 객체도 깊은 복사가 가능했다면 비효율적이라고 한다.
객체의 프로퍼티 수가 늘어날 수록 그것을 복사하고 메모리에 저장하고 또 동작시키기까지 걸리는 시간이 길어지기 때문이다.
어차피 기존 객체와 복사 객체가 같다고 생각할거라면, 기존 객체를 참조해서 보라는 시각인 것 같다.
✏️ 추후 메모리와 연관지어서 더 깊이 공부한 뒤, 다시 블로그 글을 작성해 보겠다!
let obj1 = { name: "mingming" };
let obj2 = { ...obj1 }; // spread의 사용
console.log(obj1); // { name: "mingming" }
console.log(obj2); // { name: "mingming" }
console.log(obj1 === obj2); // false
obj2.age = { age: 24 };
console.log(obj1); // { name: "mingming" }
console.log(obj2); // {name: 'mingming', age:24}
console.log(obj1 === obj2); // false
내가 가장 많이 사용하고 있는 spread 연산자이다.
spread 연산자의 사용으로 결과값이 다르게 출력되는 것을 확인할 수 있다.
let array1 = [1, 2, 3, 4];
let array2 = array1.slice();
console.log(array1); // [1, 2, 3, 4]
console.log(array2); // [1, 2, 3, 4]
console.log(array1 === array2); // false
array2.push(7);
console.log(array1); // [1, 2, 3, 4]
console.log(array2); // [1, 2, 3, 4, 7]
console.log(array1 === array2); // false
배열은 slice 메서드를 활용할 수도 있다.
다시 객체로 예를 들어 보겠다.
let obj1 = { name: "mingming", birth: [2023, 11, 5] };
let obj2 = { ...obj1 };
console.log(obj1); // { name: "mingming", birth: [2023, 11, 5] }
console.log(obj2); // { name: "mingming", birth: [2023, 11, 5] }
console.log(obj1 === obj2); // false
obj2.age = 24;
console.log(obj2); // {name: 'mingming', birth: [2023, 11, 5], age:24}
obj2.birth[0] = 1111;
console.log(obj1); // {name: 'mingming', birth: [1111, 11, 5], age:24}
console.log(obj2); // {name: 'mingming', birth: [1111, 11, 5], age:24}
console.log(obj1 === obj2); // false
obj1
객체에 birth
라는 배열을 넣어 보았다.spread
를 활용해 깊은 복사를 했기 때문에, obj2
에만 age
가 추가되었다.obj2
의 배열도 변경시켜주었는데, 이번에는 obj1
도 같이 값이 변경되었다. 😰이를 통해 위 방법들은 객체의 한단계 까지만 깊은 복사 된다는 것을 알 수 있다.
let obj1 = { name: "mingming", birth: [2023, 11, 5] };
let obj2 = JSON.parse(JSON.stringify(obj1));
console.log(obj1);// { name: "mingming", birth: [2023, 11, 5] }
console.log(obj2);// { name: "mingming", birth: [2023, 11, 5] }
console.log(obj1 === obj2); // false
obj2.age = 24;
obj2.birth[0] = 1111;
console.log(obj1);// { name: "mingming", birth: [2023, 11, 5] }
console.log(obj2); // {name: 'mingming', birth: [1111, 11, 5], age:24}
console.log(obj1 === obj2); // false
JSON을 사용하여 우리가 원하는대로 잘 작동하는 것을 확인할 수 있다!
하지만 Json으로 Serialize 되는 것들만 먹힌다.
그래서 그런가 이 방법은 절대 권장되지 않는다고 한다. 🙅♀️
깊은 복사 하고 싶으면? Lodash 라이브러리를 써라!
끝!
👉🏻 찐으로 깊은 복사가 하고 싶어? 참고 영상