언어/자바스크립트

[Javascript] 깊은복사, 얕은복사

youngble 2022. 6. 8. 19:30

객체를 복사할때 객체안에 직접적인 프로퍼티에 해당한다면 (1차복사, 얕은복사)값만 복사하여 복사한 객체의 프로퍼티값을 바꾸거나 원본객체의 프로퍼티값을 바꿔도 서로 같은것을 참조하지않기 때문에 서로 다른값의 프로퍼티가 된다. 하지만 객체 안의 프로퍼티가 또다른 객체를 가지고 있다면(2차 복사, 깊은복사) 이는 깊은 복사가 필요하다. 만약 깊은복사를 하지않는다면 원본객체에서 값을 바꾸면 복사된 객체에서도 값이 바뀌게 된다.
즉 불변객체를 만들어줘야한다.

이때 깊은 복사하는 방법은 몇가지 있다.

1. 재귀함수

var copyObject = function(target){
    var result ={};
    if(typeof target==='object'&& target!==null){
        for(var prop in target){
            result[prop] = copyObject(target[prop]);
        }
    }
    else{
        result = target;
    }
    return result;
}

위와 같이 해당 매개변수 target에 들어갈 객체를 복사하여 return 하여 copyObject에 넣어주는 함수를 만들어주었다.

var user = {
    name: 'Jaenam',
    urls: {
        portfolio:'http://github.com/abc',
        blog:'http://blog.com',
        facebook:'http://facebook.com/abc'
    }
}
var user2= copyObject(user);
user.urls.portfolio='http://portfolio.com';
console.log(user.urls.portfolio, user2.urls.portfolio)

만약 위와같이 user라는 객체를 만들고 프로퍼티로 각각 name, urls 가 있다. urls 같은경우 단순 기본데이터를 담은게 아닌 다시 객체타입으로 이루워졌기때문에 재귀함수를 통해 portfolio, blog, facebook 프로퍼티값을 복사하여 result[prop]에 넣어준다.

결과

http://portfolio.com 
http://github.com/abc

 

2. JSON 문법 stringify, parse

 

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

JSON 객체 문법을 사용하여 json 형식을 stringify() 메서드를 사용하여 문자열로 만들어주고 parse를 사용하여 다시 json형식으로 만들어주면 서로다른 불변객체가 된다.

var obj = {
  a: 1,
  b: {
    c: null,
    d: [1, 2],
    func1: function () {
      console.log(3);
    },
  },
  func2: function () {
    console.log(4);
  },
};
var obj2 = copyObjectViaJSON(obj);
obj2.a=3;
obj2.b.c=4;
obj.b.d[1] = 3;
console.log(obj.func2);
console.log(obj2.func2)

위와 같이 obj 와 obj를 JSON을 이용하여 복사한 obj2 가 있고 obj2의 프로퍼티값을 바꾸거나 obj의 프로퍼티값을 바꾸어도 서로 다른 불변객체이기때문에 다른 console을 통해 서로 다른 영향을 받지 않는 결과를 확인할수 있다. 하지만 JSON으로 문자열을 만들어줄때 function, __proto__, setter/getter 등과 같이 순수한 정보가 아니라면 문자열로 만들수없기때문에 무시되어 없어진다.
따라서 httprequest로 받는 순수한 정보를 활용하여 복사할때 유용하지만 그런게 아니라면 메서드나, 숨겨진 프로퍼티 등을 복사할때는 사용할수없다.

결과

[Function: func2]
undefined