cs 지식/코어 자바스크립트

[코어자바스크립트] 얕은 복사와 깊은 복사

귤먹는코더 2022. 5. 31. 22:57
728x90

 

 

얕은 복사와 깊은 복사

  • 얕은 복사(shallow copy)는 바로 아래 단계의 값만 복사하는 방법이고, 깊은 복사(deep copy)는 내부의 모든 값들을 하나하나 찾아서 전부 복사하는 방법입니다. 
  • 얕은 복사는 중첩된 객체에서 참조형 데이터가 저장된 프로퍼티를 복사할 때 그 주솟값만 복사한다는 의미입니다.해당 프로퍼티에 대해 원본과 사본이 모두 동일한 참조형 데이터의 주소를 가리키게 됩니다. 사본을 바꾸면 원본도 바뀌고, 원본을 바꾸면 사본도 바뀝니다.

중첩된 객체에 대한 얕은 복사

var copyObject = function (target) {
    var result = {};
    for (var prop in target) {
        result[prop] = target[prop];
    }
    return result;
}


var user = {
    name: 'Jaenam',
    urls: {
        portfolio: 'http://github.com/abc',
        blog: 'http://blog.com',
        facebook: "http://facebook.com/abc"
    }
};
var user2 = copyObject(user);

user2.name = 'Jung';
console.log(user.name === user2.name);                     //false

user.urls.portfolio = 'http://portfolio.com';
console.log(user.urls.portfolio === user2.urls.portfolio); // true

user2.urls.blog = '';
console.log(user.urls.blog === user2.urls.blog);           // true

 user 객체에 직접 속한 프로퍼티에 대해서는 복사해서 완전히 새로운 데이터가 만들어진 반면, 한 단계 더 들어간 urls의 내부 프로퍼티들은 기존 데이터를 그대로 참조하는 것이다. 이런 현상이 발생하지 않게 하려면 user.urls 프로퍼티에 대해서도 불변 객체로 만들 필요가 있다.

 

중첩된 객체에 대한 깊은 복사

var user2 = copyObject(user);
user2.urls = copyObject(user.urls);

user.urls.portfolio = 'http://portfolio.com';
console.log(user.urls.portfolio === user2.urls.portfolio); //false

user2.urls.blog = '';
console.log(user.urls.blog === user2.urls.blog);           //false

2번째 줄에서는 urls 프로퍼티에 copyObject 함수를 실행한 결과를 할당했다. 이제 urls 프로퍼티의 내부까지 복사해서 새로운 데이터가 만들어졌으므로 5번째 줄과 8번째 줄에서 값이 서로 다르다는 결과를 얻을 수 있다.
그러니까 어떤 객체를 복사할 때 객체 내부의 모든 값을 복사해서 완전히 새로운 데이터를 만들고자 할 때, 객체의 프로퍼티 중에서 그 값이 기본형 데이터일 경우에는 그대로 복사하면 되지만 참조형 데이터는 다시 그 내부의 프로퍼티들을 복사해야 합니다.

 

객체의 깊은 복사를 수행하는 범용함수(copyObject 함수를 깊은 복사 방식으로 고친 코드)

var copyObjectDeep = function (target){
    var result = {};
    if (typeof target === 'object' && target !== null){
        for (var prop in target){
            result[prop] = copyObjectDeep(target[prop]);
        }
    } else {
        result = target;
    }
    return result;
}

 

728x90