🎀 기본형과 참조형

할당이나 연산할 때 값을 복사하면 기본형이고, 주소를 복사하면 참조형이다.

🎀 깊은 복사 (Deep Copy)

기존 값의 주소가 같이 복사되는 것이 아니라 내용만 빼와서 복사된다. 깊은 복사된 값이 변경되어도 기존 값은 변경되지 않는다.

📌 기본형의 기본 특징이다.

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

기본형 타입의 깊은 복사는 값이 변경될 때, 서로에게 영향을 주지 않았다.
이게 바로 깊은 복사이다.

🎀 얕은 복사 (Shallow Copy)

기존 값의 주소를 같이 복사해온다. 얕은 복사된 값이 변경되면 기존 값도 같이 변경된다.

📌 참조형의 기본 특징이다.

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가 추가된 것을 확인할 수 있다.
참조형은 주소를 복사해 공유하기 때문에 서로에게 영향을 준다.

👉🏻 참고 블로그 바로가기

🎀 왜 참조형(객체)만 얕은 복사일까?


👉🏻 왜 하나로 통일하지 않았지? (참고 영상)

기본형과 같이 객체도 깊은 복사가 가능했다면 비효율적이라고 한다.
객체의 프로퍼티 수가 늘어날 수록 그것을 복사하고 메모리에 저장하고 또 동작시키기까지 걸리는 시간이 길어지기 때문이다.

어차피 기존 객체와 복사 객체가 같다고 생각할거라면, 기존 객체를 참조해서 보라는 시각인 것 같다.

✏️ 추후 메모리와 연관지어서 더 깊이 공부한 뒤, 다시 블로그 글을 작성해 보겠다!

🎀 하지만 객체도 깊은 복사하고 싶어!

📌 spread 연산자 (배열에도 사용 가능)

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 연산자의 사용으로 결과값이 다르게 출력되는 것을 확인할 수 있다.

📌 Array.slice()

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
  1. obj1 객체에 birth 라는 배열을 넣어 보았다.
  2. spread를 활용해 깊은 복사를 했기 때문에, obj2 에만 age가 추가되었다.
  3. obj2의 배열도 변경시켜주었는데, 이번에는 obj1도 같이 값이 변경되었다. 😰

이를 통해 위 방법들은 객체의 한단계 까지만 깊은 복사 된다는 것을 알 수 있다.

📌 JSON.parse(JSON.stringify())

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 되는 것들만 먹힌다.
그래서 그런가 이 방법은 절대 권장되지 않는다고 한다. 🙅‍♀️

🎀 진짜_진짜_최종.js

깊은 복사 하고 싶으면? Lodash 라이브러리를 써라!

끝!

👉🏻 찐으로 깊은 복사가 하고 싶어? 참고 영상




profile
일단 해. 그리고 잘 되면 잘 된 거, 잘 못되면 그냥 해본 거!

0개의 댓글