JS deep copy

WonCheol Park·2021년 6월 5일

Javascript 기본

목록 보기
7/7

시작하며

js sortable 라이브러리를 사용하는 중 deep copy를 필요로 하는 상황이 있었다. 그런데 spread 문법을 통해 (완벽한)deep copy가 가능할 거라고 생각했던 부분에서 오류가 있었다는 것을 알게 되었고, deep copy에 대해 정리해보기로 하였다.
총 4가지 방법으로 (1. json, 2. spread, 3. custom function, 4. lodash) deep copy하는 방법을 소개하고, 어떤 상황에서 각 방법을 사용하면 좋을지 간단히 정리했다.

1. json문법을 사용한 deep copy

const newObject = JSON.parse(JSON.stringify(oldObject));

object를 stringify -> parse 과정을 통한 deep copy인데 함수를 포함하는 경우에는 복사되지 않는다.

ex)

  • 함수를 포함하는 경우 복사되지 않음
const oldObject = {a:'1',b: () => {console.log('hi');}};
const newObject = JSON.parse(JSON.stringify(oldObject));
console.log(newObject); // {a: "1"}

2. spread를 사용한 deep copy

ES6 spread 문법을 사용해서도 deep copy가 가능하나 1 level의 array, object에서만 deep copy가 가능하다.

ex)

  • 1차원 array에서는 deepCopy가 가능
const foo = [1,2,3];
const bar = [...foo]; // deepcopy
  • 2~고차원 array에서 shallowCopy됨
const foo = [[1,2],3];
const bar = [...foo];
foo[0].push(3);
console.log(bar); // [[1,2,3],3]

이후 소개할 lodash의 deepCopy 방법보다 성능은 더 좋아서 1차원의 object, array만 다루는 상황이면 사용해볼만 한 것 같다.
lodash deepCopy vs spread deepCopy benchmark

3. deep copy 함수 만들어 사용하기

reduce와 재귀를 통해서 2차원 이상의 object, array에서도 새로운 객체를 반환하게끔 함수를 만들어 deep copy할 수 있다.
다음은 stack overflow출처 코드로 object, array, Date 객체까지 deep copy한 결과를 반환해주는 함수다.

function deepCopy(obj) {
    if(typeof obj !== 'object' || obj === null) {
        return obj;
    }

    if(obj instanceof Date) {
        return new Date(obj.getTime());
    }

    if(obj instanceof Array) {
        return obj.reduce((arr, item, i) => {
            arr[i] = deepCopy(item);
            return arr;
        }, []);
    }

    if(obj instanceof Object) {
        return Object.keys(obj).reduce((newObj, key) => {
            newObj[key] = deepCopy(obj[key]);
            return newObj;
        }, {})
    }
}

이후 소개할 lodash를 사용한 deep copy와 비교했을때, lodash를 사용하지 않는 환경이라면 이 방법을 사용해도 좋은 것 같다. deep copy만을 위해 사이즈 큰 lodash를 import하기에는 비효율적인 것 같다.

<몇 가지 모듈 크기 비교>

4. lodash의 cloneDeep 사용하기

lodash에서 cloneDeep이라는 함수로 간단하게 deep copy를 할 수 있다.
가장 간단하고 명확한 방법으로 대체적으로 해당 방법을 추천한다.

newObj = _.cloneDeep(obj);
profile
신입 개발자입니다~

0개의 댓글