Language/JAVASCRIPT & JQUERY

데이터 깊은 복사 , 얕은 복사

Sinnak86 2019. 6. 24. 14:45

자바스크립트에서 데이터를 대입, 즉 '=' 를 이용하거나 복사라는 개념으로 사용 하였는데 원하지 않게 데이터가 바뀔때가 있다.

 

자바스크립트는 기본 데이터형(string, numberm boolean, null, undefined)등의 데이터를 복사 할 때는 call by value방식, (Object, Array) 형식의 데이터를 복사 할 때는 call by reference 방식이다. 이유는 메모리 절약을 위해 Object 나 Array형식의 데이터는 원본 Object,Array 데이터의 주소만 참조하고 있다는 것이다.

 

일단 위  내용을 이해했다면 아래와 같은 코드는 해당 결과를 갖게 된다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 
var tester = "sinnak";    //기본형 원본 데이터
var tmpTester = "";    //기본형 데이터를 복사 할 위치
 
tmpTester = tester;
 
console.log(tmpTester);    //결과 : "sinnak"
 
var testerObj = {};
testerObj.tester = "sinnak";    //Object형 원본 데이터
var tmpTesterObj = {};
tmpTesterObj.tester = "";    //Object형 데이터를 복사 할 위치
 
tmpTesterObj = testerObj;
 
console.log(tmpTesterObj.tester);    //결과 : "sinnak"
cs

 

하지만 여기까지는 기본형 데이터 대입(복사)와 Object형 데이터 대입(복사)의 차이가 무엇인지 알수 없다.

보통 위와 같은 방식으로 데이터를 대입(복사) 하려는 이유가 복사한 데이터(위 코드에선 tmpTester, tmpTesterObj)를 사용하여 데이터 변경,수정,등의 제어를 위해 사용하게 될것이다. 이때  call by value방식과 call by reference방식의 차이를 아래와 같이 볼수 있다.

 

1
2
3
4
5
6
7
8
9
10
11
tmpTester = "Quirino";    //복사한 기본형 데이터 변경
console.log(tmpTester);    //결과 : "Quirino"
console.log(tester)    //결과 : "sinnak"
 
//기본형 데이터 대입은 값만 복사했기때문에 tmpTester의 값을 변경하여도 원본데이터의 변경이 없다.
 
tmpTesterObj.tester = "Quirino";    //복사한 Object 데이터 변경
console.log(tmpTesterObj.tester);    //결과 : "Quirino"
console.log(testerObj.tester);    //결과 : "Quirino"
 
//Object형 데이터 대입은 원본 Object의 참조값을 복사했기때문에 tmpTesterObj의 값을 변경하면 원본 데이터의 값도 변경된다.
cs

 

자바스크립트에서 흔이 하는 실수는 위와 같이 동작하는 것을 모르거나 까먹고 위 소스코드 9번줄의 testerObj.tester의 값이 "sinnak"으로 나올거란 생각을 하게될수 있다는 것이다. 왜냐면 복사를 한거라고만 생각하기 때문.

그렇다면 Object 나 Array의 데이터형도 기본데이터형의 방식데로 '복사' 하는 방법이 없을까?

이것을 깊은 복사 라고 한다.

깊은 복사를 하게 되면 Object의 데이터를 복사하면 원본데이터의 값들을 전부 복사하기 때문에 복사된 데이터를 수정하여도 원본데이터의 변경이 없다.

 

아래와 같이 jQuery, javascript를 사용하여 사용 할 수 있다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//jQuery 를 사용한 깊은 복사
var originalObj = {};
originalObj.num = 12345;
 
var tmpObj = {};
 
tmpObj = jQuery.extend(true, {}, originalObj);    
//jQuery.extend메소드 설명
//extend메소드의 첫번째 인자가 true이면 깊은복사, false면 얕은복사가 된다.
//두번째 인자는 {} 는 Object를, [] 는 Array를 명시해준다.
//세번째 인자로 복사할 원본데이터 명을 명시한다.
 
tmpObj.num = 99999;
 
console.log(tmpObj.num);    //결과 : 99999
console.log(originalObj.num);    //결과 : 12345
cs

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//자바스크립트 재귀함수를 이용한 깊은 복사
var originalObj = {};
originalObj.num = 12345;
 
var tmpObj = {};
 
//아래의 함수를 만들어 사용
function cloneObject(obj) {
    var clone = {};
    for(var i in obj) {
        if(typeof(obj[i])=="object" && obj[i] != null)
            clone[i] = cloneObject(obj[i]);
        else
            clone[i] = obj[i];
    }
    return clone;
}
 
tmpObj = cloneObject(originalObj);
 
tmpObj.num = 77777;
 
console.log(tmpObj.num);    //결과 : 77777
console.log(originalObj.num);    //결과 : 12345
cs

 

요약 : '=' 는 기본형데이터는 대입, Object/Array형 데이터는 복사의 의미를 혼돈하지 말자