4.2 참조에 의한 객체 복사
객체와 원시 타입의 근본적인 차이
_ 원시값(문자열, 숫자, 불린값)은 값 그대로 저장, 할당, 복사되는 반면 참조에 의해(by reference)저장, 복사됨
//원시형
let message = "Hello!";
let phrase = message;
console.log(message); //Hello
console.log(phrase); //Hello
//객체형
let user = {
name: "John"
};
let admin = user; // 참조값을 복사함
admin.name = 'Pete'; //참조 값이 변경됨
alert(user.name); // 'Pete'가 출력됨. 참조 값이 변경되었으므로 'admin' 또한 변경됨
: 변수엔 객체가 그대로 저장되는 것이 아니라 객체가 저장된 '메모리 주소'인 객체에 대한 '참조값'이 저장됨
ex) 서랍장의 열쇠가 두개이고 그 중 하나(객체)를 사용해 서랍장을 정리하면 나머지 다른 열쇠로 서랍장을 열었을 때도 서랍장이 정돈된 상태
- 참조에 의한 비교
객체 비교시 동등 연산자(==)와 일치 연산자(===)는 동일하게 동작 ???질문) 왜?
비교 시 피연산자인 두 객체가 동일한 객체인 경우에 참(true)을 반환
let a = {};
let b = a; // 참조에 의한 복사
alert( a == b ); // true, 두 변수는 같은 객체를 참조합니다.
alert( a === b ); // true
//독립된 객체
let a = {};
let b = {}; // 독립된 두 객체
alert( a == b ); // false
cf) obj1>obj2 같은 대소비교, obj ==5같은 원시값과의 비교에서는 객체가 원시형으로 변환됨
- 객체 복사, 병합과 Object.assign
자바스크립트는 기본으로 객체 복제 내장 메서드를 지원하지않으므로 객체 복사가 필요할 경우에는
1. 기존 객체의 프로퍼티들을 순회해 원시수준까지 복사
let user = {
name: "John",
age: 30
};
let clone = {}; // 새로운 빈 객체
// 빈 객체에 user 프로퍼티 전부를 복사해 넣습니다.
for (let key in user) {
clone[key] = user[key];
}
// 이제 clone은 완전히 독립적인 복제본이 되었습니다.
clone.name = "Pete"; // clone의 데이터를 변경합니다.
alert( user.name ); // 기존 객체에는 여전히 John이 있습니다.
2. Object.assign 사용
Object.assign(dest, [src1, src2, src3...])
//dest : 목표로 하는 객체
//src1, src2.. : 복사하고자 하는 객체
//src1, src2읙 프로퍼티를 dest에 복사
//dest를 제외한 인수(객체)의 프로퍼티 전부가 첫번째 인수(객체)로 복사
//dest 반환
let user = { name: "John" };
let permissions1 = { canView: true };
let permissions2 = { canEdit: true };
// permissions1과 permissions2의 프로퍼티를 user로 복사합니다.
Object.assign(user, permissions1, permissions2);
// now user = { name: "John", canView: true, canEdit: true }
목표 객체(user)에 동일한 이름의 프로퍼티가 있는 경우엔 기존 값이 덮어씌어짐
- 중첩 객체 복사
프로퍼티가 다른 객체의대한 참조값일 경우
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[key]의 각 값을 검사하면서 객체인 경우 객체의 구조도 복사해주는 반복문을 사용하는 '깊은 복사(deep cloning)'을 사용해야 함
-> Structured cloning algorithm을 사용하면 다양한 상황의 객체 복사 가능
-> 자바스크립트 라이브러리 lodash의 메서드인 _.cloneDeep(obj)을 사용하여 깊은 복사 처리 가능
요약
객체는 참조에 의해 할당, 복사되어 객체의 변수에는 '객체'자체가 아닌 '참조'라는 메모리상의 주소가 복사됨. 따라서 객체가 할당된 변수를 복사하거나 함수의 인자로 넘길 때는 객체가 아닌 객체의 참조가 복사됨
따라서 복사된 참조를 이용한 모든 작업(프로퍼티 추가, 삭제 등)은 동일한 객체를 대상으로 이루어짐
객체의 '진짜 복사본'을 만들기 위해서는 Object.assign을 이용한 '얕은 복사(shallow copy)-중첩객체 처리x' 나 _cloneDeep)obj)를 사용해 '깊은 복사'를 활용
'JS > [web] 코어 JS 튜토리얼' 카테고리의 다른 글
[코어 JS] 4.4 - 객체: 메서드와 this (0) | 2021.10.04 |
---|---|
[코어 JS] 4.3 - 객체: 가비지 컬렉션 (0) | 2021.10.03 |
[코어 JS] 4.1 - 객체: 기본 (0) | 2021.10.03 |
[코어 JS] 3 - 코드 품질 (0) | 2021.09.27 |
[코어 JS] 2 - 자바스크립트 기본(2) (0) | 2021.09.27 |