#TIL21

전혜린·2021년 8월 15일
0

Today I Learned

목록 보기
33/64

얕은 복사와 깊은 복사

const user = {
name: 'hyerin',
age: 95,
emails: ['abcde@gmail.com']
}
const copyUser = user
console.log(copyUser === user) //true

user.age = 22
console.log('user', user) //user {name: "hyerin", age: 22, emails: Array(1)}
console.log('copyUser',copyUser) //copyUser {name: "hyerin", age: 22, emails: Array(1)}

  • user라는 변수와 copyUser 변수가 바라보고 있는 메모리주소가 같기 때문에 한쪽에서 수정을 해도 다른쪽도 영향을 받음
  • 동일하게 copyUser를 수정 하더라도 user 부분의 값도 변경될 것임
  • 이러한 현상을 통해 의도치않게 엉뚱한 부분이 수정될 수 있음

얕은 복사(Shallow copy)

1. Object.assign()을 사용하여 복사

  • 첫번째 인수는 대상객체, 두번째 인수는 출처객체로 대상객체에 출처객체가 가지고있는 여러가지 속성들을 담고 그것을 실행해서 반환
  • 새로운 객체데이터가 새로운 메모리주소에 할당됨

const user = {
name: 'hyerin',
age: 95,
emails: ['abcde@gmail.com']
}
const copyUser = Object.assign({}, user)
console.log(copyUser === user) //false

  • false: user가 가지고 있는 속성과 값들을 복사해서 집어 넣었기 때문에 겉표면의 객체데이터는 1번 메모리주소, 2번 메모리주소로 일치하지 않음

user.age = 22
console.log('user', user) //user {name: "hyerin", age: 22, emails: Array(1)}
console.log('copyUser',copyUser) //copyUser {name: "hyerin", age: 95, emails: Array(1)}

  • user.age부분은 22로 갱신, user부분을 수정한 것이 copyUser 변수에는 영향을 미치지 않음

 
2. 전개 연산자(Spread)를 사용하여 복사

  • 하나의 빈 객체데이터 내부에 user라는 객체데이터가 가지고있는 속성과 값들을 전개해서 집어넣게 됨

const user = {
name: 'hyerin',
age: 95,
emails: ['abcde@gmail.com']
}
const copyUser = {...user}
console.log(copyUser === user) //false

  • false: 새로운 메모리주소로 할당 됐기에 일치하지 않음

user.age = 22
console.log('user', user) //user {name: "hyerin", age: 22, emails: Array(1)}
console.log('copyUser',copyUser) //copyUser {name: "hyerin", age: 95, emails: Array(1)}

  • user.age부분은 22로 갱신, user부분을 수정한 것이 copyUser 변수에는 영향을 미치지 않음

얕은복사의 문제점

  • 배열데이터의 가장 뒷부분에 새로운 아이템으로 push 부분의 인수를 집어 넣음
  • 현재 복사 처리한 것은 user라는 객체데이터, 결국 user안에 들어 있는 새로운 참조형 데이터인 emails라는 배열데이터는 따로 복사된 것이아닌 같은 메모리주소를 공유중 이므로 일치연산자의 값이 true
  • 즉, age 부분의 숫자는 다르지만 참조형 데이터인 emails의 배열은 같은 메모리주소를 공유하는 상태

const user = {
name: 'hyerin',
age: 95,
emails: ['abcde@gmail.com']
}
const copyUser = {...user}
console.log(copyUser === user) //false

user.emails.push('xyz@naver.com')
console.log(user.emails === copyUser.emails) //true
console.log('user', user) //{name: "hyerin", age: 22, emails: Array(2)}
//emails: (2) ["abcde@gmail.com", "xyz@naver.com"]
console.log('copyUser',copyUser) //{name: "hyerin", age: 95, emails: Array(2)}
//emails: (2) ["abcde@gmail.com", "xyz@naver.com"]


깊은 복사(Deep copy)

  • lodash 패키지의 도움을 받아 cloneDeep 메소드 사용
  • clone:복제 deep:깊은 즉, 깊은 복제를 만듦을 의미
  • 참조형 데이터 내부에 또다른 참조형 데이터가 있다면 얕은 복사 보다는 깊은 복사를 통해서 복사하는 것이 안전

const copyUser = _.cloneDeep(user)
console.log(copyUser === user) //false

user.age = 22
console.log('user', user) //{name: "hyerin", age: 22, emails: Array(1)}
console.log('copyUser',copyUser) //{name: "hyerin", age: 95, emails: Array(1)}

user.emails.push('xyz@naver.com')
console.log(user.emails === copyUser.emails) //false
console.log('user', user)
//{name: "hyerin", age: 22, emails: Array(2)}
// emails: (2) ["abcde@gmail.com", "xyz@naver.com"]
console.log('copyUser',copyUser) //{name: "hyerin", age: 95, emails: Array(1)}

정리

  • 객체 데이터, 배열 데이터 같은 참조형 데이터를 복사할 때, 얕은 복사로도 충분히 문제없이 복사가 가능하다고 판단할 때 Object.assign이나 전개 연산자를 통해 해당하는 참조형 데이터를 복사
  • 쉽게말해 대표적인 참조형데이터인 객체 및 배열데이터를 복사할 때에는 그 내부에 또다른 참조형 데이터가 없다는 전제 하에서는 손쉽게 얕은 복사를 사용해도 무방
  • 하지만, 특정 참조 데이터 내부에 또 다른 참조형 데이터가 있다면 깊은 복사를 고려해야 함
  • 깊은 복사인 lodash의 cloneDeep 기능의 도움을 받아 개발하는 것을 추천

예시

  • false: objects의 배열데이터라는 껍데기만 복사하는 것이 아니라 그 내부에 들어있는 새로운 참조형 데이터인 객체데이터까지 꼼꼼하게 복사해서 새로운 메모리로 할당했기에 그 내부에 있는 값을 비교해도 일치연산자에서 false 값이 나옴

출처) https://lodash.com/docs/4.17.15#cloneDeep

profile
코딩쪼아

0개의 댓글