연관된 내용
[JavaScript의 type]
객체를 복사해 오면, 복사해 온 사본의 값을 바꿨을 때 원본도 바뀌게 되는데, 그 이유는 얕은 복사가 일어났기 때문이다.
이를 막기 위해서는 깊은 복사를 이용해야 한다.
모든 데이터 타입은 값 타입 또는 참조 타입(Object)을 가진다.
값 타입은 각각의 고유의 메모리를 소유하는 것이고, 참조 타입은 생성된 인스턴스들이 주소 값을 공유하는 것이다.
값 타입을 복사하면 깊은 복사가 일어나고, 참조 타입을 복사하는 경우 얕은 복사가 일어난다.
/*복사 당할 객체*/
let Me = {
name : "주희" ,
info : { //중첩 객체: 객체 안의 객체
mbti : "ESTJ",
position : "프론트엔드"
}
}
/*객체 복사해오기*/
let copyObject = function(target){
let result = {}
// 객체의 프로퍼티를 순회하며 복사해오기
for(let key in target){
result[key]=target[key]
}
return result;
}
let friend = copyObject(Me)
/*사본 객체의 값 바꾸기*/
friend.name = "주희2"
friend.info.position = "백엔드"
/*원본과 사본의 프로퍼티 비교*/
console.log(friend.name , Me.name)
// friend.name = "주희2" , Me.name = "주희"
console.log(friend.info.position , Me.info.position)
//friend.info.position = "백엔드" , Me.info.position = "백엔드"
얕은 복사
주소 값을 복사 하는 것!
So, 참조하고 있는 실제 값은 같다!!!
얕은 복사는 중첩 객체(예제의 info)의 값을 참조해오는 것으로, 할당된 value 자체를 복사하는 것이 아니고 메모리 주소를 참조해 온다.
따라서, Me와 friends의 info가 가리키고 있는 메모리 주소가 같기 때문에 사본을 수정하면 원본도 같이 수정되는 것이다.
얕은 복사를 하게 되면 인스턴스가 메모리에 새로 생성되지 않아 깊은 복사보다 상대적으로 빠르다.
깊은 복사
실제 값을 복사 하는 것!
깊은 복사는 얕은 복사와 반대로 원본 객체에 할당된 value 자체를 복사해 사본 객체에 새로 할당해준다.
따라서 사본을 수정해도 메모리 주소가 서로 다르기 때문에 원본이 수정되지 않는다.
객체와 배열에는 주소가 들어있고, 데이터는 그 주소에 담겨있는 것이다.
주소가 복사되었기 때문에, 같은 데이터를 공유하게 되는 것이다.
그렇다면 어떻게 복사하지? (값을 공유하지 않도록)
복사는 없음..ㅎㅎ 최대한 복사와 비슷하게 ㄱㄱ
새로 만들고 안의 내용들을 하나 하나 따로 넣어줘야 한다.
{중괄호}
를 열면 새로 만드는 것이 된다. (다른 새로운 주소에 할당됨)
좀 쉽게(짧게) 쓸 수 있게 나온 것이 스프레드 연산자이다.
중괄호 안의 내용을 ...profile
로 바꿔서 쓸 수 있다.
이것도 {중괄호}를 열고 안에 넣었기 때문에 새로 주소가 만들어진다.
But, 객체 안의 객체에 대해서는 여전히 복사가 아닌 주소 공유가 이뤄지게 된다.
이렇게 1단계까지만 복사되는 것을 얕은 복사라고 한다.
JSON.parse(JSON.stringify(복사할 객체))
객체 전체를 문자열로 바꾸면 {중괄호}
가 주소가 아니라 그냥 문자열이 된다.
이렇게 객체를 문자열로 바꾸고, 다시 객체로 바꾸면
깊이에 관여하지 않고 아예 새로 만드는 것이 되기 때문에 복사가 된다.
JSON.stringify(객체)
문자열로 바꿔준다.
JSON.parse(문자열)
문자열을 객체나 배열로 바꿔준다.
참고:
"
를 문자열로 입력할 때는\"
활용
위 방식은 속도가 느리다. lodash 라이브러리를 사용해서 보완할 수 있다.
쓸모 있는 기능들을 만들어놓은 라이브러리이다.
깊은 복사 기능이 만들어져 있다.
_
로 import 해서 많이 사용한다. --> _
로 되어 있는 것은 lodash일 확률이 높다!
import _ from lodash
배열도 객체와 똑같이 작동한다.
[참고] 객체를 const로 선언하면 마지막 코드처럼
{중괄호}
를 써서 다른 주소를 저장할 수 없다. 내용물은 바꿀 수 있다!!