-
객체를 복사할 때 유의할 점JavaScript 2021. 4. 28. 22:04
자바스크립트에서 객체와 원시값의 큰 차이점 중 하나는 값이 할당되고 복사되는 방식이다. 어떤 변수에 값을 값을 할당하거나 복사할 때 원시값은 값 자체를 할당/복사 하는 반면, 객체는 그 객체가 저장되있는 메모리 주소인 '참조 값(reference)'이 복사된다.
let origin = { awesomeKey: 'awesomeValue'}; let copied = origin;
예시 코드에서 변수는 두 개지만(origin, copied) 각 변수는 동일한 객체에 대한 참조 값이 담긴다. 둘 다 같은 객체를 바라보고 있기 때문에 변수 copied를 가지고 객체의 값을 변경했을 때 origin도 함께 변경된다.
copied.awesomeKey = 'beautifulValue' origin.awesomeKey === 'beautifulValue' // true
위 예시 처럼 참조 값을 복사하는 것이 아니라, 독립된 복사본 객체를 만들고 싶을 땐 어떻게 해야할까? 복사하고자 하는 객체의 모든 프로퍼티가 원시값이라면 단순히 for...in문을 사용해 객체를 순회하면서 복사하거나 Object.assign을 사용할 수 있다.
예시1. for...in
let origin = { awesomeKey: 'awesomeValue', myKey: 'myValue', yourKey: 'yourValue', }; let copied = {}; for(let key in origin) { copied[key] = origin[key]; } copied.myKey = 'myCoolValue' console.log(origin.myKey) // 'myValue'
예시2. Object.assign
let origin = { awesomeKey: 'awesomeValue', myKey: 'myValue', yourKey: 'yourValue', }; let copied = Object.assign({}, origin) copied.yourKey = 'yourElegantValue'; console.log(origin.yourKey) // yourValue
위 방법은 객체의 모든 프로퍼티가 원시값인 경우만 가정한 방법이다. 만약 객체의 프로퍼티가 원시값이 아닌 다른 객체에 대한 참조값이 온다면, 복사하려는 객체의 프로퍼티에 값을 할당할 때도 역시 참조값이 할당된다.
JSON.Stringify, JSON.parse를 이용할 수도 있다. 하지만 성능상의 단점이 있고, 프로퍼티에 함수가 오는 경우에는 JSON.Stringify가 함수를 undefiend로 처리한다는 문제가 있다.
이런 문제를 해결하려면 원본 객체의 모든 프로퍼티값을 검사하면서, 값이 객체인 경우 객체의 구조까지 복사해주는 방식으로 반복문을 작성해야 한다. 이것을 깊은 복사(deep copy)라고 한다. 자바스크립트 라이브러리 lodash의 _.cloneDeep(obj) 메서드를 이용하면 간편하게 깊은 복사를 할 수 있다.
'JavaScript' 카테고리의 다른 글
반복문 빠져나오기 - break, continue, label (0) 2021.04.22 이벤트 버블링(bubbling) (0) 2021.03.04 클로저(closure) (0) 2020.12.07 "use strict" (0) 2020.12.04 호이스팅 (0) 2020.10.28