본문 바로가기
JS 공부

JS문법종합반 정리 3주차 02 - 객체 복제, 얕은 복사, 깊은 복사

by 나노다 2024. 11. 6.

객체 복제의 문제점

 객체를 변수에 직접 할당하는 식으로 통째로 복제하면, 복제된 객체의 프로퍼티를 변경할지라도 불변성 땜시 기존 객체와 복사 객체가 같다고 판단됨. 

/* 기존 객체 */
var user = {
	name: 'wonjang',
	gender: 'male',
};

/* 객체를 복사하고, name 프로퍼티의 값을 바꾸는 함수 */
var changeName = function (user, newName) {
	var newUser = user;
	newUser.name = newName;
	return newUser;
};

/* 복사 객체 생성 */
var user2 = changeName(user, 'twojang');

/* name의 값이 다름에도 불구하고 두 객체가 같다고 판단 */
console.log(user === user2); // 반환 : true

 

 

얕은 복사

 기존 객체와 내용물은 같은 아예 새 배열을 생성하는 식으로 복제를하면 복사 객체와 다르다고 판단함. 하지만 중첩 객체인 경우 하위 객체의 복제는 역시 기존 것과 같다고 판단...

/* 기존 객체 (중첩 객체) */
var user = {
	name: 'wonjang',
	urls: {
		portfolio: 'http://github.com/abc',
		blog: 'http://blog.com',
		facebook: 'http://facebook.com/abc',
	}
};

/* 얕은 복사 함수 */
var copyObject = function (target) {
	// 새 객체를 만듦
    var result = {};
    // 새 객체에 기존 객체의 프로퍼티를 옮겨 닮음
	for (var prop in target) {
		result[prop] = target[prop];
	}
	return result;
}

/* 복제 객체 생성 */
var user2 = copyObject(user);

/* 상위 프로퍼티 변경 시 다르다 판단 */
user2.name = 'twojang';
console.log(user.name === user2.name); // false

/* 하위 프로퍼티 변경했음에도 불구하고 같다 판단 */
user.urls.portfolio = 'http://portfolio.com';
console.log(user.urls.portfolio === user2.urls.portfolio); // true

 

 

깊은 복사

 재귀적 수행을 통해 중첩 객체의 프로퍼티 중 기본형 데이터는 그냥 복제, 참조형 데이터는 다시 그 내부의 프로퍼티를 복제하는 방법을 통해 온전히 다른 복제 객체를 만들 수 있음

  • 재귀적 수행 : 함수나 알고리즘이 자기 자신을 호출해 반복 실행하는 것
/* 기존 객체 (중첩에 중첩 객체임) */
var obj = {
	a: 1,
	b: { c: null, d : [1, 2], }
};

/* 깊은 복사 함수 */
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;
}

/* 복제 객체 생성 */
var obj2 = copyObjectDeep(obj);

/* 복제 객체의 프로퍼티 변경 */
obj2.a = 3;
obj2.b.c = 4;
obj2.b.d[1] = 3;

/* 중첩객체 속 모든 요소가 달라졌음 */
console.log(obj === obj2); // 반환 : false
console.log(obj.b.c === obj2.b.c); // 반환 : false
console.log(obj.b.d[1] === obj2.b.d[1]); // 반환 : false