코드/JavaScript

얕은 복사와 깊은 복사

juundev 2024. 5. 17. 15:05

얕은 복사와 깊은 복사

얕은 복사(shallow copy) - 바로 아래 단계의 값만 복사하는 방법

깊은 복사(deep copy) - 내부의 모든 값들을 하나하나 전부 복사하는 방법

 

다음은 얕은 복사를 구현한 함수와 객체 복사 결과를 보여주는 코드이다.

// 기존 정보를 복사해서 새로운 객체를 반환하는 함수 (얕은 복사)
var copyObject = function(target) {
    var result = {};
    for (var item in target){
    	result[item] = target[item];
    }
}

var user = {
    name: 'kim',
    info: {
        gender: 'male',
        age: '26'
    }
};

var user2 = copyObject(user);

// 기본형 데이터는 얕은 복사만으로 완전히 새로운 데이터가 만들어진다.
user2.name = 'park';
console.log(user === user2 ? "일치" : "불일치"); // 불일치

// 중첩된 객체에서 참조형 데이터가 저장된 데이터를 복사할 때에는 주솟값만 복사하여 원본과 사본이 모두 동일한 주소를 가리킨다.
// 사본을 바꾸면 원본도 바뀌고, 원본을 바꾸면 사본도 바뀐다.
user2.info.gender = 'female';
console.log(user.info.gender === user2.info.gender ? "일치" : "불일치") // 일치
user.info.age = '25';
console.log(user.info.age === user2.info.age ? "일치" : 불일치) // 일치

 

위의 코드를 통해 user 객체에 직접 속한 프로퍼티에 대해서는 복사 후 완전히 새로운 데이터가 만들어진 반면, 중첩된 객체인 info 내부의 프로퍼티는 기존 데이터를 그대로 참조하여 같은 주소를 가리킵니다. 따라서 user2.info.gender를 female로 변경하면 user.info.gender 또한 female을 갖습니다.

 

어떤 객체를 복사할 때 객체 내부의 모든 프로퍼티를 복사해서 완전히 새로운 데이터를 만들고자 할 때에는, 객체의 프로퍼티 중에서 그 값이 기본형 데이터일 경우에는 그대로 복사하고, 참조형 데이터는 그 내부의 프로퍼티들을 재귀적으로 복사해야 합니다.

 

다음은 깊은 복사를 구현한 함수와 객체 복사 결과를 보여주는 코드이다.

 

var copyObjectDeep = function(target) {
    var result = {};
    // target이 객체인 경우에는 내부 프로퍼티를 순회하며 copyObjectDeep 함수를 재귀적으로 호출한다.
    // target !== null 조건은 typeof 명령어가 null에 대해서도 object를 반환하기 때문이다.
    if (typeof target === 'object' && target !== null) {
    	for (var item in target) {
        	result[item] = copyObjectDeep(target[item]);
        }
    // 객체가 아닌 경우에는 기본형 데이터의 복사 방식으로 복사한다.
    } else {
    	result = target;
    }
    return result;
};

 

위의 코드에 있는 copyObjectDeep 함수를 사용하여 객체를 복사하면 원본과 사본이 서로 완전히 다른 객체를 참조하게 되어 한쪽의 프로퍼티를 변경하더라도 다른 쪽에 영향을 주지 않습니다.

 


만약 내가 개발을 하면서 객체를 복사하여 독립적으로 사용하고자 한다면, 위의 방식보다는 더 간단한 방법을 찾고자 할 것 같습니다.

 

다음은 JSON을 활용하여 간단하게 깊은 복사를 구현하는 코드이다.

 

var copyObjectViaJson = function(target) {
    return JSON.parse(JSON.stringify(target));
};

 

위의 코드는 객체를 JSON 문법으로 표현된 문자열로 전환했다가 다시 JSON 객체로 변환하는 코드입니다. 

단, 메서드(함수)나 숨겨진 프로퍼티인 __proto__나 getter/setter 등과 같이 JSON으로 변경할 수 없는 프로퍼티들은 무시합니다.

httpRequest로 받은 데이터를 저장한 객체를 복사할 때 등, 순수한 정보만 다룰 때 활용하기 좋은 방법입니다.

 

코어 자바스크립트: 핵심 개념과 동작 원리로 이해하는 자바스크립트 프로그래밍을

공부하며 이해한 내용을 기반으로 정리한 게시글입니다.

'코드 > JavaScript' 카테고리의 다른 글

자바스크립트 클래스  (0) 2024.05.29
자바스크립트 프로토타입  (0) 2024.05.24
클로저  (0) 2024.05.22
콜백함수 (Callback)  (0) 2024.05.17
undefined와 null의 차이  (0) 2024.05.17