자바스크립트 데이터 타입은 크게 원시형(기본형: Primitive Type), 참조형(Reference Type)으로 나뉜다.
이 때 원시형은 값을 복사할 때 다른 메모리에 할당하기 때문에 사본 값이 변해도 원본에 영향을 미치지 않는다.
반면 참조형은 복사를 해도 메모리 주소가 같은 값을 가리키기 때문에 원본과 사본이 같은 주소를 참조한다고 이야기한다. 그래서 사본이 바뀌면 원본에도 영향을 미친다.
원시형은 number, string, boolean, null, defined 등이 있고
참조형은 object,symbol 등이 있다,
즉, 정리를 하면
깊은 복사(Deep Copy)
원시형 데이터에서 복사되는 방식이고 메모리를 재할당하는 개념
사본이 변경되어도 원본에는 영향 없음
얕은 복사(Shallow Copy)
참조형에서 복사되는 방식
메모리 공간을 할당하는게 아니라 주소값을 복사하는 개념, 사본이 변경되면 원본도 바뀜
cf) 객체에서의 깊은 복사?
정확하게는 객체에서 depth 1까지는 깊은 복사를 할 수 있다.
이때 깊은 복사는 스프레스 연산자 ... 를 사용한다.
depth 1: 기본 객체 형태
const person = {
age: 30,
name: '철수'
}
const copy={...person} //깊은 복사
copy.age=20 //사본 키 값 변경
//원본과 사본 값 비교
console.log(copy) // { age: 20, name: '철수' }
console.log(person) // { age: 30, name: '철수' }
원본과 사본 키(age) 값이 서로 다른 것을 확인할 수 있다. (깊은 복사 잘 됨)
또는 이렇게 스프레드 연산자로 깊은 복사 + 키 값 변경을 한번에 할 수 있다.
const copy2={...person,age:20}
depth 2 이상(객체 안에 객체, 객체 안에 객체 안에 객체 ,...)
depth 1처럼 스프레드 연산자로 똑같이 복사하고 객체 안에 객체 키 값을 바꾸게 되면 얕은 복사가 된다.
const profile = {
id:"1",
person:{
age: 30,
name: '철수'
}
}
const copy={...profile}
copy.person.age=10 //사본 profile 객체 안의 person 객체의 키 값 변경
//원본과 사본 값 비교
console.log(copy)//{ id: '1', person: { age: 10, name: '철수' } }
console.log(person)//{ id: '1', person: { age: 10, name: '철수' } }
얕은복사가 돼서 원본을 안 건드렸는데도 값이 바뀐다.
객체 안에 객체가 있는 경우에는 원본과의 참조가 완전히 끊어진다는 것을 의미하므로 깊은 복사가 안된다고 한다.
그렇지만!! 깊은 복사를 할 수 있는 방법이 있다.
여러 방법이 있는데 대표적으로 JSON 객체 메소드 두 개를 사용하면 된다.
JSON 객체 메소드
예시 객체)
const origin = {
a: 1,
b: "string",
c: {
name: "Leon",
age: "29"
}
};
JSON.stringify : 자바스크립트 값이나 객체를 JSON 문자열로 변환하는 메소드
적용
JSON.stringify(origin)
//결과
'{"a":1,"b":"string","c":{"name":"Leon","age":"29"}}
```'
JSON.parse : JSON 문자열의 구문을 분석하고 그 결과에서 자바스크립트 값 또는 객체를 생성하는 메소드
매개변수로 문자열이 들어오므로 보통 JSON.stringify와 같이 사용한다.
적용
JSON.parse(JSON.stringify(origin))
//결과
{
a: 1,
b: 'string',
c: { name: 'Leon', age: '29' }
}
->객체 안에 객체 깊은 복사 실행->잘 된다!
const copy=JSON.parse(JSON.stringify(origin))
copy.c.age="2"
console.log(origin)
//결과
{
a: 1,
b: 'string',
c: { name: 'Leon', age: '29' }
}
JSON 메소드를 이용하면 편하긴 하지만 속도가 느리다는 단점이 있다.