참조와 복사 (feat 깊은 복사, 얕은 복사)

taehyunkim·2021년 1월 23일
2

자바스크립트

목록 보기
4/5

참조와 복사

얕은 복사 = 참조, 깊은 복사 = 복사

원시값은 값을 복사할 때 복사된 값을 다른 메모리에 할당함으로 기존 값과 복사된 값이 서로 연관이 없다
하지만, 참조값은 변수가 객체의 주소를 가리키므로 기존 값과 복사된 값이 같다.

자료형 중에서 원시 자료형 (스트링, 넘버, 불린)은 위 조건을 모두 만족한다.
복사한 데이터를 변경해도 원본 데이터는 멀쩡!!

하지만, 참조 자료형 (객체, 배열, 함수)는 다르게 동작한다!!

복제인간(복사본)을 바꿨는데 사람(원본 데이터)도 변해버리고 마는 것이다

객체는 이렇게 값이 연결되어 있어서 대입 연산을 하게 되면 참조 관계(얕은 복사)가 성립된다

객체는 객체, 함수, 배열을 일컬어 객체라 한다.

객체를 복사할때는 객체 자체는 복사가 안되고 참조가 되므로 객체 안의 요소, 원시값들을 복사해야 한다.

객체 간의 참조관계인지 알아보려면 비교연산자(===)를 사용해서 알아보면 된다
=> true가 나오면 참조관계! 즉, 둘은 연결되어 있다!

근데 이렇게 모양이 똑같으면 같은거 아니냐??

아니다 객체는 모양이 똑같아도 다를 수 있다

모양 뿐만 아니라 똑같아지려면 참조관계를 만들어주어야 한다

Object.keys와 forEach를 사용하여 객체를 복사할 수 있다. 참조의 연결고리를 끊을 수 있다는 말씀!

하지만, 객체 안의 객체는 복사가 안되고 참조가 된다
왜냐하면 a는 원시 자료형이므로 복사가 되었지만 b는 객체로 참조 자료형이므로 복사가 안되고 참조가 되기 때문!

이럴때는 다음과 같이 재귀함수를 써서 해결할 수 있다

그런데 이 방법은 너무 복잡하다
JSON.parse와 JSON.stringify를 쓰면 훨씬 간단하게 만들 수 있다

하지만 이것도 완전한 깊은 복사가 아니니...
완전한 깊은 복사를 구현하는 것은 매우 어렵다

배열의 경우에는 slice()를 쓰면 더 간단히 고칠 수 있다

하지만 이것도 완벽한 깊은 복사가 아니란다...

정리

원시값들 스트링, 넘버, 불린은 복사가 되고 (원본을 변경시키지 않음) 객체들 객체, 배열, 함수는 참조가 된다 (원본을 변경시킴)

참조형 데이터를 복사시키려면 Object.keys와 forEach를 사용하거나 slice를 사용하거나 JSON.parse, JSON.stringify를 사용한다.

JSON.parse, JSON.stringify 방식은 함수는 안된다, 배열 객체는 된다

객체 안의 객체 형태, 즉 객체가 중첩된다면 JSON의 parse와 stringify를 사용해야 한다
하지만 성능면에 있어서 최악이기 때문에 안 쓰는걸 추천 (게다가 이것도 완전한 깊은복사가 아니란다)

완전한 깊은복사를 구현해 내려면 어떻게 해야하는걸까?? 🧐

lodash clonedeep 사용하면 완전한 깊은 복사를 할 수 있습니다.

출처 : 제로초 유튜브 https://www.youtube.com/watch?v=VEg7zmjNPaY

profile
프론트엔드 개발자

0개의 댓글