[Javascript] js 깊은 복사(Deep Copy), 객체 복제(Clone Object)
자바스크립트 문자열(String)과 숫자(Number)는 native 타입이어서 또 다른 변수에 대입하면 동일해진다(값 복사).
그러나 객체(Object)와 배열(Array)은 또 다른 변수에 대입하면 참조 상태(개념적으로 보면 일종의 포인터만 갖고 있는 상태)가 된다.
관련한 오류를 피하려면 얕은 복사(Shallow Copy) 대신 깊은 복사(Deep Copy)를 수행해야 한다.
객체/배열을 복사해서 새로운(기존과 독립인) 새로운 객체/배열을 만드는 것이다.
자바스크립트 깊은 복사는 eval을 쓰는 등 여러가지 방법이 있다.
1. JSON 객체를 사용한 깊은 복사 (객체/배열 복제)
JSON 객체를 사용해서 깊은 복사를 한다. 먼저 문자열로 만들고, 문자열을 다시 파싱하는 식이다.
|
// js 깊은 복사 function deepCopy(_obj) { if (_obj == null) { return null; }
return JSON.parse(JSON.stringify(_obj)); }
|
2. 직접 구현한 깊은 복사 (객체/배열 복제)
아래는 JSON 객체를 사용하지 않고 직접 짠 함수다. 이 함수의 특징/사용상 주의사항은 다음과 같다.
1. 객체(Object, {}) 또는 배열(Array, [])을 깊은 복사한다.
2. 함수(Function)는 복사하지 않는다.
3. 배열과 객체의 구분은 length 요소가 있는지로 판별한다.
(배열이 아닌데 하필 length 요소가 존재한다면 오류가 발생할 수 있다.)
4. 리턴용 객체 인스턴스를 만들 때 생성자를 활용하지 않는다.
(생성자를 활용하려면 var newObj = new Object(); 대신 var newObj = _obj.constructor(); 식으로 코딩하면 된다.)
|
// js객체를 깊은 복사한다. function deepCopy(_obj) { if (_obj == null || typeof(_obj) == null) { return null; }
// 숫자 복사 if (typeof(_obj) == “number”) { return parseInt(_obj + “”, 10); }
// 문자열 복사 if (typeof(_obj) == “string”) { return _obj + “”; }
if (typeof(_obj) == “object”) { var bArray = false; try { // 배열 여부는 length 로만 판단한다. if (_obj.length === parseInt(_obj.length, 10)) { bArray = true; } } catch (e) {} // 배열 복사 if (bArray) { var newArray = new Array(); var cnt = _obj.length; for (var i=0; i<cnt; i++) { newArray[i] = deepCopy(_obj[i]); } return newArray; } // 객체 복사 var newObj = new Object(); for (var attr in _obj) { if (_obj.hasOwnProperty(attr)) { newObj[attr] = deepCopy(_obj[attr]); } } return newObj; }
// 숫자, 문자열, 배열 외에는 복사하지 않는다. (ex: function) return null; }
|