객체 - 참조에 의한 객체 복사
객체와 원시 타입의 근본적인 차이
객체를 변수에 저장하면
1. 객체는 메모리 내 어딘가에 저장되고
2. 변수에는 객체가 메모리 내 어디에 위치하는지 알려주는 참조값이 저장된다.
따라서 객체가 할당된 변수를 복사할 때는 객체의 참조값이 복사되고 객체는 복사되지 않는다.
따라서 하나의 객체에 접근하거나 조작할 땐 여러 변수를 사용할 수 있다.
let user = { name: 'John'};
let admin = user; // 변수 admin에 user에 저장된 객체의 참조 값을 복사함
admin.age: 30; // 'admin' 참조 값에 의해 변경됨
alert(user.age); // 30이 출력됨, 'user' 참조 값을 이용해 변경사항을 확인함
참조에 의한 비교
두 변수가 같은 객체를 참조하는 경우 ==,=== 둘 다 true 반환
let a = {};
let b = a; // 참조에 의한 복사
alert( a == b ); // true, 두 변수는 같은 객체를 참조합니다.
alert( a === b ); // true
이번에는 두 객체가 둘 다 비어있는 객체지만, 두 객체는 서로 다른 참조값을 가지기 때문에 동등(==),일치(===)하지 않다.
let a = {};
let b = {};
alert( a == b ); // false
alert( a === b ); // false
객체 복사
Object.assign 사용
Object.assign(객체1,객체2,객체3, ... )
객체1 - 목표로 하는 객체
객체2, 객체3 - 복사하고자 하는 객체
사용 예시
let user = { name: "John" };
let permissions1 = { canView: true };
let permissions2 = { canEdit: true };
let permissions3 = { name: "Janna" };
// permissions1과 permissions2의 프로퍼티를 user로 복사합니다.
Object.assign(user, permissions1, permissions2, permission3);
// now user = { name: "Janna", canView: true, canEdit: true }
여기서 name같이 복사할 객체에 동일한 이름을 가진 프로퍼티가 있는 경우에는 기존 값이 덮어씌워 진다.
중첩 객체 복사
프로퍼티가 다른 객체에 대한 참조 값인 경우
Object.assign : 얕은 복사
let user = {
name: "John",
sizes: {
height: 182,
width: 50
}
};
let clone = Object.assign({}, user);
alert( user.sizes === clone.sizes ); // true, 같은 객체입니다.
// user와 clone는 sizes를 공유합니다.
user.sizes.width++; // 한 객체에서 프로퍼티를 변경합니다.
alert(clone.sizes.width); // 51, 다른 객체에서 변경 사항을 확인할 수 있습니다.
user객체의 sizes는 객체의 참조값이다.
따라서 프로퍼티를 복사하는 것 만으로는 객체를 복사할 수 없다. Ojbect.assign으로 복사해도 참조값이 복사돼서 같은 sizes를 공유하게 된다.
이 문제를 해결하려면 user[key]의 각 값을 검사하면서, 그 값이 객체인 경우 객체의 구조도 복사해주는 반복문을 사용해야 한다.
이런 방식을 '깊은 복사(deep cloning)'라고 한다.
자바스크립트 라이브러리 lodash의 메서드 _.cloneDeep(obj)를 사용해서 깊은 복사를 처리할 수 있다.