❓ 원시타입에서 얕은복사와 깊은복사가 일어나지 못하는 이유는?
원시타입(String,Number,Null,undefined,Boolean,Symbol,bigInt)들은 값에 의한 전달,
즉 원시타입 자료형을 다른 변수에 할당 시 그 값자체가 복사되기 때문이다.
값 자체가 복사 되기때문에, 할당한 새로운 변수는 전에 변수와 다른 독립적인 존재이다.
let num1 = 42;
let num2 = num1; // 실제 값 복사 (참조가 아님)
num1
과 num2
는 각기 다른 메모리 영역으로 저장되고,
서로 독립적인 값을 가지므로 원본 변수에 영향을 주지 ❌
얕은복사와 깊은복사가 필요한 이유는
참조타입인 객체와 배열에서 변수를 다른 변수에 할당할때 값이 아닌 참조가 복사되기 때문에
참조형데이터 타입의 복사, 같은 메모리 주소를 공유하고 있다
참조에의한 복사
란 객체를 복사할때 원본 값과 복사된 값이 같은 메모리 주소를 가르키는 경우를 나타낸다참조에의한 복사
를 하게되면 서로 같은 메모리 주소를 공유하기때문에 원본값을 복사한 값의 변경시 원본값에도 영향이가게 된다let origin = { name: 'Jinny' }
let copy = origin;
copy.name = 'Mr.Lee';
//원본 객체에도 영향이 가는 모습
console.log(origin); // 'Mr.Lee'
console.log(copy); // ''Mr.Lee;
console.log(origin === copy) // true 메모리 주소값을 공유하기 때문에 true가 출력된다
copy
의 name
값을 변경했음에도 불구하고, 원본 origin
의name
이 변경되었다
Object.assign()
메서드는 주어진 source 객체들에서 열거 가능한 모든 속상 값을 target 객체로 복사할 수 있다' //target ➡️ 목표 객체, 소스 객체의 프로퍼티를 복사 후 반영한 후 반환할 객체
//source ➡️ 출처 객체, 목표 객체에 반영하고자 하는 프로퍼티를 제공
Object.assign(target,source)
🚨주의
Object.assign()
를 사용하면, 객체 자체는 깊은 복사가 수행되지만, 2차원 이상(객체 안의 객체)는 얕은 복사가 수행된다.
const sourceObject = {name : "seju", age:"26", gender:"male"}
//원본 sourceObject의 프로퍼티값 Object.assign()으로 복사함
const copyObject = Object.assign({},sourceObject)
console.log(copyObject)
console.log(sourceObject === copyObject) //false
copyObject
가 sourceObject
의 값은 복사했으나, 메모리 주소는 복사되었지 않기때문에 비교했을때 false
가 나오는 모습이다
copyObject
에 새로운 name을 할당해도, 기존의 sourceObject
는 변화가 없다
전개 연산자(...)
을 써도 객체에 대한 깊은복사가 가능하다.🚨주의 전개연산자도
Object.assign()
과 같이 2차원 이상부터(객체의 객체등등)에 대한값들은 얕은복사가 된다
const obj = {name : 'seju', age : '25' , 사는곳 : "서울"}
//spread oprator로 원본 obj의 프로퍼티들을 전재
const spreadObj = {...obj}
console.log(obj);
console.log(spreadObj)
전개연산자로 복사한 spreadObj
와 obj
를 콘솔로그로 찍어본 모습
전개연산자로 복사한 spreadObj
와 obj
비교 값만 복사되었기때문에 비교시 false
가 나오고 spreadObj
의 값을 변경시에도, 원본 객체인 obj
의 값의 변화는 없다
이러한 중첩된 프로퍼티에 객체를 포함하는 객체 복사를 깊은복사
라고한다.
여기서 깊은 복사를 수행하려면 여러가지 방법이 있는데 대표적으로,
Object.assign()
_.cloneDeep(obj)
사용하기deepCopy Function
만들기function cloneDeep(object) {
return Object.fromEntries(
Object.entries(object).map(([key, value]) => {
let type = typeof value;
if (value && type === 'object') {
value = cloneDeep(value);
}
return [key, value];
})
);
}