글 작성자: 망고좋아
반응형

 

참조에 의한 객체 복사

  • 원시값(문자열, 숫자, 불린 값)은 ‘값 그대로’ 저장·할당되고 복사된다.
// 원시값 복사 방식
let message = "Hello!";
let phrase = message;
  • 독립된 변수에 각각 문자열 "Hello!"가 저장된다.

  • 하지만, 객체는 원시 타입과 달리 ‘참조에 의해(by reference)’ 저장되고 복사된다.
  • 변수엔 객체가 그대로 저장되는 것이 아니라, 객체가 저장되어 있는 '메모리 주소'인 객체에 대한 '참조 값'이 저장된다.
// 객체 복사 방식
let user = {
    name: "Jhon"
};

  • 객체는 메모리 내 어딘가에 저장되고, 변수 user엔 객체를 '참조’할 수 있는 값이 저장된다.
  • 따라서 객체가 할당된 변수를 복사할 땐 객체의 참조 값이 복사되고 객체는 복사되지 않는다.
let user = { name: "John" };

let admin = user; // 참조값을 복사함
  • 변수는 2개지만 각 변수에 동일 객체에 대한 참조 값이 저장되고 있다.

  • 따라서 객체에 접근하거나 객체를 조작할 땐 여러 변수를 사용할 수 있다.
let user = { name: 'John'};
let admin = user;

admin.name = 'Pete'; // 참조값 변경
alert(user.name); // 변경된 pete 출력
  • 객체는 서랍장, 변수는 서랍장을 열 수 있는 열쇠
  • 서랍장은 하나, 서랍장을 열 수 있는 열쇠는 2개
  • 그중 admin을 사용해 서랍장을 열어 정돈한 후, 또 다른 열쇠로 서랍장을 열면 정돈된 내용을 볼 수 있다.

 

참조에 의한 비교

  • 객체 비교 시 =====는 동일하게 동작한다.
  • 비교 시 피연산자인 두 객체가 동일한 객체인 경우에 참을 반환한다.
let a = {};
let b = a; // 참조에 의한 복사

alert( a == b ); // true, 두 변수는 같은 객체를 참조합니다.
alert( a === b ); // true

//-------------------------

// 객체가 같아 보여도 독립된 개체이기 때문에 거짓이 반환된다.
let a = {};
let b = {}; // 독립된 두 객체

alert( a == b ); // false

 

 

객체 복사, 병합과 Object.assign

  • 객체 복사하고 싶을 때 사용
  • 하지만 객체를 복사해야 하는 일은 거의 없다.
  • 대부분 참조에 의한 복사로 해결 가능한 일이 대부분이기 때문에
  • Object.assign을 사용하지 않으면은 새로운 객체 생성 후 for문으로 하나하나 복사하면 된다.(비 추천)

 

Object.assign 기본 문법

Object.assign(dest, [src1, src2, src3...])
  • dest는 목표로 하는 객체
  • 뒤에 이어지는 인수는 복사하고자 하는 객체
  • 객체 src1, src2, src3의 프로퍼티를 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 }
  • 만약 목표 객체에 동일한 이름을 가진 프로퍼티가 있는 경우엔 덮어쓰기를 한다.

 

객체 복사

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

let clone = Object.accign({}, user)l

 

 

중첩 객체 복사

  • 복사하려는 프로퍼티가 다른 객체에 대한 참조 값일 때는 어떻게 해야 될까?
let uer = {
    name: "John",
    sizes: {
        height: 182,
        width: 50
    }
};
alert(user.sizes.height) // 182
  • clone.sizes = user.sizes로 프로퍼티를 복사하는 것만으론 객체를 복제할 수 없다.
  • user.sizes는 객체이기 때문에 참조 값이 복사되기 때문이다.
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, 다른 객체에서 변경 
  • 이렇게 되면 객체 복사를 한 게 아니다.
  • 객체의 '진짜 복사본’을 만들려면 '얕은 복사(shallow copy)'를 가능하게 해주는 Object.assign이나 '깊은 복사’를 가능하게 해주는.cloneDeep(obj)을 사용하면 된다.
  • 이때 얕은 복사본은 중첩 객체를 처리하지 못 해준다.

 

 

📌 참고

반응형