본문 바로가기

모던 자바스크립트

4.2 객체 - 참조에 의한 객체 복사

참조에 의한 객체 복사

📢 객체는 참조에 의해(by reference) 저장되고 복사된다. 

 

◾️ 변수엔 객체가 그대로 저장되는 것이 아니라, 객체가 저장 되어 있는 '메모리 주소'인 객체에 대한 '참조 값'이 저장된다.

◾️ 객체는 메모리 내 어딘가에 저장되고, 변수에는 객체를 '참조❗️'할 수 있는 값이 저장된다.  

◾️ 객체가 할당된 변수를 복사할 땐 객체의 참조 값만 복사되고 객체는 복사되지 않는다. 

◾️ 변수는 두 개 이지만 각 변수엔 동일 객체에 대한 참조값이 저장된다. 

let user = { name: "suzu" };
let admin = user;

admin.name = 'ruru';

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

 

참조에 의한 비교

📢 객체 비교 시 피연산자인 두 객체가 동일 객체인 경우에는 참을 반환한다. 

let a = {};
let b = a; // 참조에 의한 복사

console.log( a == b ); // true
console.log( a === b ); // true

◾️ 겉 보기에는 객체 a,b가 같아보이지만, 독립된 객체이기 때문에 거짓을 반환한다. 

let a = {};
let b = {};

console.log( a == b ); // false

◾️ obj1 > obj2 같은 대소 비교나 obj == 5 같은 원시값과의 비교에선 객체가 원시형으로 변환된다. 

 

 

객체 복사, 병합과 Object.assign

◾️ 자바스크립트는 객체 복제 내장 메서드를 지원하지 않는다. 

◾️ 방법 1 : 새로운 객체를 만든 다음 기존 객체의 프로퍼티들을 순회해 원시 수준까지 프로퍼티를 복사하면 된다. 

let user = { name: 'suzu', age: 30 };

let clone = {}; 

for (let key in user) {
  clone[key] = user[key];
}

clone.name = 'ruru'

console.log(clone); // { name: 'ruru', age: 30 }
console.log(user.name); // suzu

◾️ 방법 2 : Object.assign

Object.assign(dest, [src1, src2, src3...])

      ◾️ dest : 목표로 하는 객체

      ◾️ src1, ..., srcN : 복사하고자 하는 객체(여러개 사용 가능)

      ◾️ 객체 src1, ..., srcN의 프로퍼티를 dest에 복사한다. dest를 제외한 객체의 프로퍼티 전부가 첫 번째 객체로 복사된다. 

      ◾️ dest를 반환한다. 

      ◾️ dest에 동일한 이름을 가진 프로퍼티가 있는 경우엔 기존 값이 덮어 씌워진다. 

 

let user = { name: "suzu" };

let userInfo1 = { age: 30 };
let userInfo2 = { role: 'admin' };
let userInfo3 = { name: 'ruru' };

Object.assign(user, userInfo1, userInfo2, userInfo3);

console.log(user)// { name: 'ruru', age: 30, role: 'admin' }

◾️ 방법 1을 Object.assign을 사용하면 반복문 없이도 간단하게 객체를 복사할 수 있다. 

let user = { name: 'suzu', age: 30 };

let clone = Object.assign({}, user); 

console.log(clone); // { name: 'suzu', age: 30 }

 

 

중첩 객체 복사

◾️ 프로퍼티는 다른 객체에 대한 참조 값일 수도 있다. 

◾️ Object.assign을 사용해도 clone.size는 독립된 객체가 아닌 참조 값이 복사된다. 

let user = {
  name: "suzu",
  sizes: {
    height: 160,
    width: 50
  }
};

let clone = Object.assign({}, user);

console.log( user.sizes === clone.sizes ); // true

user.sizes.width++;
console.log(clone.sizes.width); // 51

얕은 복사(shallow copy)

◾️ 가장 상위 객체만 새로 생성되고 내부 객체들은 참조 관계인 경우

깊은 복사(deep cloning)

◾️ user[key]의 각 값을 검사하면서, 그 값이 객체인 경우 객체의 구조도 복사해주는 반복문을 사용해야 한다. 

function deepCopyObject(obj) {
   let clone = {};
    for(var i in obj) {
        if(typeof(obj[i])=="object" && obj[i] != null)
            clone[i] = deepCopyObject(obj[i]);
        else
            clone[i] = obj[i];
    }
    return clone;
}

let user = {
  name: "suzu",
  sizes: {
    height: 162,
    width: 50
  }
};

let result = deepCopyObject(user);
result.sizes.height = 150;

console.log(result.sizes.height); // 150;
console.log(user.sizes.height); // 162

◾️ Structured cloning algorithm : 깊은 복사 시 사용되는 표준 알고리즘

◾️ 자바스크립트 라이브러리 lodash의 메서드인 _.cloneDeep(obj)를 사용

 

 

 



📝 오늘 새롭게 배운 내용 📝

 

✅ 객체의 복사
: 312호 방에 들어가기 위해 열쇠(key1)를 복사(key2)한 것과 같다. 
key1과 key2의 이름은 다르지만 같은 방에 들어 갈 수 있다. 

✅ Object.assign

✅ 얕은 복사, 깊은 복사

 

 

 

📌 [JAVASCRIPT_INFO 참조에 의한 객체 복사] 

 

참조에 의한 객체 복사

 

ko.javascript.info

📌 [MDN Object.assign]

 

Object.assign()

Object.assign() 메소드는 열거할 수 있는 하나 이상의 출처 객체로부터 대상 객체로 속성을 복사할 때 사용합니다. 대상 객체를 반환합니다.

developer.mozilla.org

 

 

 

'모던 자바스크립트' 카테고리의 다른 글

4.5 'new' 연산자와 생성자 함수  (0) 2020.08.10
4.4 메서드와 'this'  (0) 2020.08.08
4.3 가비지 컬렉션  (0) 2020.08.06
4.1 객체 - 객체  (0) 2020.08.04
모던 JavaScript 정독하기  (0) 2020.08.04