[모던 JavaScript 튜토리얼] - [4.2] 참조에 의한 객체 복사

IRISH·2024년 1월 24일
0

JS

목록 보기
42/80
post-thumbnail

학습 내용

<참조에 의한 객체 복사>

  1. 객체(Object)와 원시타입(Premitive type)의 가장 큰 차이는 객체는 참조에 의해(by reference)에 저장되고 복사된다는 것이다. 쉽게 말하면, 원시타입은 값이 그대로 저장되고, 객체는 값이 저장된 메모리주소값(참조값)이 저장된다.

  2. 객체 비교시 ==과 === 연산자는 동일하게 동작한다. 왜냐하면 메모리 주소값 자체를 비교하기 때문이다. 참조하고 있는 값이 같아도 실질적인 메모리 주소는 다르면 FALSE 뜰 것이다.

  3. 객체복사를 하고 싶으면 어떡하지?

  • 기본적으로 복제가 필요한 상황은 일어나지 않는다.
  • 만약 필요하다면 기존 객체의 프로퍼티들을 순회해서 원시 수준까지 복사를 하면 된다.
  • 복제코드 예:
let clone = {}; // 새로운 빈 객체

// 빈 객체에 user 프로퍼티 전부를 복사해 넣습니다.

for (let key in user) {

clone[key] = user[key];

}
  • 병합코드 예:
let user = { name: "John" };

let permissions1 = { canView: true };

let permissions2 = { canEdit: true };

// permissions1과 permissions2의 프로퍼티를 user로 복사합니다.

Object.assign(user, permissions1, permissions2);
  • 이런 방식을 '얕은 복사(Shallow Copy)'라고 한다.
  • 만약 객체가 객체를 프로퍼티로 가지고 있으면 어떡하지?
    • 객체가 객체를 프로퍼티로 가지고 있다면(=중첩 객체라면), 위의 방법으로는 복제가 불가능하다. 그 이유는 프로퍼티들이 원시타입이라는 전제하에 복사를 하면 프로퍼티가 객체일 경우, 복제가 아닌 복사가 되버리기 때문이다.
      • 이런 문제를 해결하기 위해서는 각 프로퍼티가 객체인지 판단하면서 객체 구조일 경우 각 구조의 원시타입까지가서 복제를 해주는 반복문을 사용해야한다.
        • 이런 방식을 '깊은 복사(Deep Cloning)'이라고 한다.
  • Structured cloning algorithm이나 lodash 라이브러리의 _.cloneDeep(obj) 메소드를 활용하면 직접 구현없이 가능하다.

실습

let user = {
    name : "pcy"
};

console.log(user.name);         // pcy

/* 참조값 복사 */
let objectCopy = user;
console.log(objectCopy.name);   // pcy

/* 참조값 수정 */
objectCopy.name = "Irish"
console.log(objectCopy.name);   // Irish
console.log(user.name); ;       // Irish

/* 참조에 의한 비교 */
// 객체 비교에서 == 과 === 은 동일한 동작
let objA =  {};
let objB = objA;                // 참조에 의한 복사
console.log(objA == objB);      // true
console.log(objA === objB);     // true

let objC =  {};
let objD = {};                  // 독립된 두 객체
console.log(objC == objD);      // false
console.log(objC === objD);     // false

/* ********************************************* */

let userInfo = {
    name: "John",
    age: 30
};

let objClone = {}; // 새로운 빈 객체

// 빈 객체에 user 프로퍼티 전부를 복사해 넣습니다.
for (let key in userInfo) {
    objClone[key] = userInfo[key];
}

// 이제 clone은 완전히 독립적인 복제본이 되었습니다.
objClone.name = "Pete"; // clone의 데이터를 변경합니다.

// 기존 객체에는 여전히 John이 있습니다.
console.log( "userInfo.name = " + userInfo.name ); // userInfo.name = John
console.log( "objClone.name = " + objClone.name ); // objClone.name = Pete

/****************** Object.assign ******************/
// 형식 : Object.assign(dest, [src1, src2, src3...])
let userAssign = { name: "John" };

let permissions1 = { canView: true };
let permissions2 = { canEdit: true };

// permissions1과 permissions2의 프로퍼티를 user로 복사합니다.
Object.assign(userAssign, permissions1, permissions2);

console.log( userAssign ); // { name: 'John', canView: true, canEdit: true }

느낀점

우선, Object가 파이썬의 딕셔너리 구조와 상당히 유사한 것으로 보인다. 그리고, 참조 개념 자체도 쉽게 이해됐다. 어려운 단원은 아니었던 것 같다.

profile
#Software Engineer #IRISH

0개의 댓글