[15]_shallow copy vs deep copy

적자생존·2022년 4월 3일
0

Javascript

목록 보기
2/11

1. 데이터 복사

원시값 : Number, String, Boolean, undefined, null, Symbol
참조값 : Object(array, function, ...)

원시값의 경우는 값을 복사할 때 복사된 값을 다른 메모리에 할당하기 때문에 원래의 값과 복사된 값이 관계가 없음
const a = 1;
let b = a
b = 2
console.log(a) //1
console.log(b) //2

즉 const a는 a라는 이름으로 집을 만들어주고 1을 집어넣음
let b 는 b라는 집을 만들어주고 a를 집어넣음 이때 a는 const a와 다름
이후 b에게 2를 할당하면
b= 2가 나오게 됨
즉 const a와 let b= a의 a가 서로 다름

하지만 참조값의 경우는 변수가 객체의 주소를 가르킴
const a = {number : 2}
let b = a
b.number = 3
console.log(a) // {number : 3}
console.log(b) // {number : 3}

여기서 const a는 a에게 {number : 2}라고 주소를 지정해줌
let b = a는 b라는 집을 만들어주고 a( {number:2} )라는 주소를 할당해주는 것
그렇게 되면 a의 값이 바뀌게 되면 b도 자동으로 바뀜

이런 특징으로 때문에 복사하는 방법이 두 가지로 나뉨

2. 얕은 복사

가. 뻐킹 하드코딩

let a = {
name : '철수',
age : 8,
school : '가나다초등학교'
}

이렇게 있으면

let b = {
name : a.name,
age : a.age,
school : a.school
}

이렇게 복사하면 코드량도 늘고 매우 좋으니 하지 않는게 좋다.

나. 스프레드 연산자

...a

let a = {
name : '철수',
age : 8,
school : '가나다초등학교'
}
let aa = { ...a }
console.log(aa)
{ name: '철수', age: 8, school: '가나다초등학교' }
aa.name = '영희'
console.log(aa)
{ name: '영희', age: 8, school: '가나다초등학교' }
console.log(a)
{ name: '철수', age: 8, school: '가나다초등학교' }

스프레드 연산자를 쓰면 원래 값(a)에 영향을 미치지 않고 수정할 수 있다.
이를 얕은 복사라고 하는데


즉 b라는 주소를 만들고 b의 주소에 a의 값을 채워 넣은거라고 생각하면 됨
그래서 b에 내용을 아무리 수정해도 a가 바뀌지 않게 됨

아래의 경우를 보면 잘 안된다

let a = {
    name:"철수",
    age:8,
    school: "다람쥐초등학교",
    hobby: {
        hobby1 : "수영",
        hobby2 : "게임"
    }
let b = { ...a}
b.hobby.hobby1 = '독서'
console.log(b)
{
    name:"철수",
    age:8,
    school: "다람쥐초등학교",
    hobby: {
        hobby1 : "독서",
        hobby2 : "게임"
    }
console.log(a)
{
    name:"철수",
    age:8,
    school: "다람쥐초등학교",
    hobby: {
        hobby1 : "독서",
        hobby2 : "게임"
    }

이런식으로 a와 b의 hobby1이 모두 바뀌게 된다
왜 그런걸까?

b라는 주소를 만들고 a라는 값을 입력한 건 위의 과정과 동일하나
이때 내부의 hobby는 새로운 주소값을 가지는데 그 주소값을 복사했기 때문에 동일한 주소를 가르키게 된것이다.

즉 참조형 값의 경우 {}, []를 씌우면 무조건 주소(고유값)이 생긴다고 생각하면 편하다.

3. 깊은 복사

가. 원리

전체를 객체가 아닌 스트링으로 만들어 버리면?
원시값이기 때문에 그냥 복사가 됨 그것을 다시 객체로 만들어 버리면 새로운 주소(고유값)이 생기게 되는 것이고 원시형을 복사했기 때문에 스트링을 복사하는 시점에서 남남이 되기 때문에 객체로 만들어도 서로 남남임

나. 사용법

JSON.stringify()로 객체로 만들고 JSON.parse({})로 새로운 배열로 만들어 버리면 새로운 배열이 하나 튀어나옴
JSON.parse(JSON.stringify())
하지만 이는 매우 느리고 deepth한 데이터에만 사용함
다. lodash 라이브러리를 이용하자

profile
적는 자만이 생존한다.

0개의 댓글