
우선 코드부터 확인해보겠습니다.
var user = {
	name: 'Jungsoo',
	urls: {
		naver: 'https://naver.com',
		insta: 'https://insta.com'
	}
}; // 객체 정의
var copyObject = function(target){
	var result = [];
	for (var prop in target) {
		result[prop] = target[prop];
	}
	return result;
}; // 객체 복사 함수 생성
var user2 = copyObject(user); // 객체 복사
user2.name = 'Jung';  // 기본형 타입 프로퍼티 변경
console.log(user.name === user2.name); // false, 불변성 성립
user2.urls.naver = 'https://www.naver.com'; // 참조형 타입 프로퍼티 변경
console.log(user.urls.naver === user2.urls.naver); // true, 불변성 성립 X  한 단계 더 들어간 urls의 내부 프로퍼티들은 기존 데이터를 그대로 참조하는 현상이 발생합니다.
이와 같이 바로 아래 단계의 값만 복사하는 것을 얕은 복사(shallow copy)라고 합니다.
이는 깊은 단계의 참조형 데이터를 복사할 때 불변성이 지켜지지 않습니다.
var user2 = copyObject(user); // 객체 복사
user2.urls = copyObject(user.urls); // 참조형 타입 복사
user2.urls.naver = 'https://www.naver.com'; // 참조형 타입 프로퍼티 변경
console.log(user.urls.naver === user2.urls.naver) // false, 불변성 성립  이처럼 참조형 데이터는 그 내부 프로퍼티들을 다시 복사해야합니다.
이를 재귀적으로 처리하면 아래와 같이 작성할 수 있습니다.
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;
}
typeof명령어는null값에 대해서도object를 반환하는 버그가 있기에
object임을 확인하는 동시에null이 아닌지도 확인해야 합니다.
  이처럼 내부의 모든 값을 하나하나 찾아서 복사하는 것을 깊은 복사(deep copy)라고 합니다.
또한 JSON으로 변환 후 복사를 진행해도 깊은 복사가 가능합니다.
var copyObjectViaJSON = function(target){
	return JSON.parse(JSON.stringify(target));
}  다만 메서드(함수), __prote__, getter/setter 등과 같이 JSON으로 변경할 수 없는 프로퍼티들을 모두 무시하기 때문에 순수한 정보만 다룰 때 이용하면 좋습니다.