ES6의 전개 (spread 연산자)를 통해 손쉽게 깊은 복사를 할 수 있습니다.
하지만 과연 전개는 완전히 깊은 복사일까요? 오늘은 전개가 완전히 깊은 복사가 아닌 경우와 그에 따른 해결방법을 글에 남기도록 하겠습니다.
글에 앞서 Spread연산자에 대해 모른다면 아래의 글을 먼저 읽어주세요
전개로 깊은 복사가 되지 않는 경우
쉽게 말해 nested 되었을 경우 내부 중첩된 요소들은 깊은 복사가 되지 않습니다.
const a = {
key: 'aVal'
}
const b = {
...a
}
b.key = 'bVal';
console.log(a);
console.log(b);
// { key: 'aVal' }
// { key: 'bVal' }
위는 깊은 복사가 진행된 경우 입니다. a를 전개한 값을 다시 객체로 묶어 b로 할당한다면 다른 객체를 참조하기에 b의 값을 바꿔도 a의 값이 바뀌지 않습니다.
const a = {
out: {
in: 'aVal'
}
}
const b = {
...a
}
b.out.in = 'bVal';
console.log(a);
console.log(b);
// { out: { in: 'bVal' } }
// { out: { in: 'bVal' } }
하지만 위와 같이 객체 안에 또 다른 객체가 존재한다면 그 내부 객체는 깊은 복사가 되지 않습니다. 물론 아래와 같이 out에 대한 값을 바꾼다면 깊은 복사가 일어납니다
const a = {
out: {
in: 'aVal'
}
}
const b = {
...a
}
b.out = null;
console.log(a);
console.log(b);
// { out: { in: 'aVal' } }
// { out: null }
위와 같은 경우는 배열또한 마찬가지 입니다.
const a = [
{
key: 'aVAl'
}
]
const b = [
...a
]
b[0].key = 'bVal';
console.log(a);
console.log(b);
// [ { key: 'bVal' } ]
// [ { key: 'bVal' } ]
배열의 바로 요소가 아닌 요소의 프로퍼티를 바꾼다면 기존의 값도 바뀌는 것을 알 수 있습니다.
nested된 객체 깊은 복사
1. JSON을 이용
const a = {
out: {
in: 'aVal'
}
}
const b = JSON.parse(JSON.stringify(a))
b.out.in = 'bVal';
console.log(a);
console.log(b);
// { out: { in: 'aVal' } }
// { out: { in: 'bVal' } }
위와 같이 JSON.parse와 JSON.stringify를 이용하면 깊은 복사를 할 수 있습니다.
JSON.stringify는 객체를 Json 문자열로 바꿔주며 JSON.parse는 Json문자열을 객체로 바꿔주는 함수입니다.
하지만 위의 방식은 성능이 느리고 만약 프로퍼티의 value가 function이라면 JSON.stringify중 undefined로 처리됩니다.
2. Lodash 패키지
NPM의 Lodash 패키지를 이용하는 방식입니다.
엄청나게 많은 사람이 다운받아 사용하여 이미 검증된 패키지입니다.
많은 메소드가 있지만 cloneDeep이라는 메소드를 이용합니다.
const { cloneDeep } = require('lodash')
const a = {
out: {
in: 'aVal'
}
}
const b = cloneDeep(a)
b.out.in = 'bVal';
console.log(a);
console.log(b);
// { out: { in: 'aVal' } }
// { out: { in: 'bVal' } }
위와 같이 간단히 cloneDeep이라는 함수로 간단히 사용할 수 있습니다.
참조 문서
'개발 > Javscript,Typescript' 카테고리의 다른 글
[JS] 순수함수 (Pure Function) (0) | 2021.03.27 |
---|---|
[JS] 클로저 (Closure) (0) | 2021.03.24 |
[JS] 자바스크립트의 동작 원리 (4) | 2021.02.04 |
[JS] Promise 잘 처리하기 (비동기 병렬) (0) | 2021.02.01 |
[JS] Promise, Async, Await 비동기 처리 (0) | 2020.11.05 |