객체를 복사할 때 참조에 의한 할당이 이루어져 원본과 같은 메모리 주소를 갖게 되
는 것
얕은 복사는 한 변수의 데이터를 변경하면 다른 변수의 데이터의 값도 함께 변경 된다. 즉, 한 데이터를 공유하고 있는 것이다. (원본=카피 -> true)
참조가 아닌 값을 그대로 복사하고 같은 값을 가지는 별개의 메모리 공간을 갖는 것
한 객체 값의 변경이 다른 객체 값의 변경에 영향을 주지 않는다. (원본=카피 ->false)
원시값은 깊은 복사를 하지만 객체는 얕은 복사을 기반으로 한다. 그리하여 객체는 한 데이터의 공유가 아니라 똑같은 구조의 객체를 하나 더 생성하여 따로 사용하고자 할 때 깊은 복사가 필요하다.
spread(...)
Object.assign()
slice()
Object.freeze()
JSON.parse(JSON.stringify(obj))
;readonly
spread(...)와 Object.assign(), slice(), Object.freeze()는 depth 1까지는 깊은 복사가 가능하지만 depth 2부터는 얕은 복사가 되므로 중첩된 객체에서는 불변성을 지키지 못한다.
JSON.stringify를 이용하여 문자(원시값)로 변환한 뒤, JSON.parse를 통해 다시 객체로 변환하여 할당하면 완전히 다른 객체로 생성되면서 깊은 복사를 할 수 있다. 단, JSON은 function, arrow function, undefined에서는 사용할 수 없다.
또한 대중적인 유틸 라이브러리(loadsh)를 사용하거나 직접 유틸 함수를 생성하는 방법도 있다.
직접 유틸 함수를 만드는 방법은 다음과 같다.
Object.freeze()
function deepFreeze(obj){
Object.keys(obj).forEach(key=>{
if(객체가 맞으면){
deepFreeze(obj[key])
}
})
return Object.freeze(obj);
}
stackoverflow 사이트에 들어가서 중첩된 객체의 깊은 복사에 대해 여러 사람들이 짜놓은 코드를 보는 것도 도움이 된다. 이 외에도 Typescript에서 readonly
메서드를 사용하는 방법 등이 있다.
filter
, map
, slice
같이 새로운 배열을 반환하는 메서드를 활용하여 원본 배열의 불변성을 지키는 방법도 있다.
배열의 불변성을 유지하는 방법
filter
, map
, slice
같이 새로운 배열을 반환하는 메서드를 활용자바스크립트에서는 값에 의한 전달만 있고, 사실상 참조에 의한 전달은 없다. 참조에 의한 전달을 뜯어보면, 결국 그것도 값(다른 값에 대한 메모리주소)에 의한 전달이기 때문이다.