shallow copy, deep copy

YOUNGJOO-YOON·2021년 5월 30일
0

JavaScript

목록 보기
2/25

TOC

  1. shallow copy

  2. deep copy


어느 언어에나 shallow copy, deep copy에 대한 이야기는 있을 것으로 생각된다.

요점

JS에서 어떤 객체를 copy하는 경우

JS의 객체는 Primitive value에 대해서는 deep copy를 한다.

이외의 다른 객체는 shallow copy를 한다는 것이 요점이다.

boolean

null

undefined

string

number


shallow copy가 발생하는 경우

Primitive 객체가 아닌 객체에 대해 shallow copy가 발생한다 예를 들면

Array

copy를 변경했는데 ary까지 같이 변경이 되었다.

이는 ary, copy가 같은 변수를 참조하고 있다는 것이다.

아래의 이미지를 하나 더 보자

ary 배열에 객체를 각각 담아 선언하고
prototype을 통해 copy를 했다

copy를 변경하고 ary를 다시 호출했더니 변경되지 않았다.

copy와 ary는
이렇게 deep copy가 되어 서로 전혀 관계가 없는 상태가 되었을까?

다른걸 시도해보자

ary[0].a 객체를 변경하고 copy를 보았더니 값이 변경되어 버렸다.

이제 슬슬 deep copy에 대해 알아보자


deep copy

const deepCopyFunction = (inputObject) => {
  let outputObject, value, key;
  outputObject = Array.isArray(inputObject) ? [] : {}; // Create an array or object to hold the values

  if (typeof inputObject !== "object" || inputObject === null) {
    return inputObject; // Return the value if inputObject is not an object
  }

  for (key in inputObject) {
    value = inputObject[key];
    outputObject[key] = deepCopyFunction(value); 
   // Recursively (deep) copy for nested objects, including arrays
  }
  return outputObject;
}

let originalArray = [10, 20, { name: "Ayush", age: 27 }];
let deepCopyArray = deepCopyFunction(originalArray);
originalArray[1] = 15;
originalArray[2].name = "Verma";

console.log(originalArray); //[10, 15, { name: "Verma", age: 27 }];
console.log(deepCopyArray); //[10, 20, { name: "Ayush", age: 27 }];

[출처] https://javascript.plainenglish.io/shallow-copy-and-deep-copy-in-javascript-a0a04104ab5c

위 블로그에서 copy에 대해 훌륭히 설명해주고 있다.

deep copy를 하는 이유는 여러가지이겠지만 원본에 대한 참조를 그만두고 싶은 경우 이 deep copy는 필수불가결한 구현요소가 된다.

따라서 위의 순수 js method를 이용해 deepcopy를 구현하거나

유명한 라이브러리인 lodash, 혹은 ramda, 아니면 rdfc를 사용하도록 하자.

// lodash
import { clone, cloneDeep } from "lodash" // Alternatively: Import just the clone methods from lodash
const nestedArr = [["1"] ,["2"] ,["3"]];
const shallowCopyWithLodashClone = _.clone(nestedArr)
console.log(nestedArr[0] === shallowCopyWithLodashClone[0]);
// true -- Shallow copy (same reference)
const deepCopyWithLodashCloneDeep = _.cloneDeep(nestedArray)
console.log(nestedArr[0] === deepCopyWithLodashCloneDeep[0]);
// false -- Deep copy (different reference)
// ramda

import R from "ramda" // Import the entire ramda library
// import { clone } from "ramda" // Alternatively: Import just the clone methods from ramda
const nestedArr = [["1"] ,["2"] ,["3"]];
const deepCopyWithRamdaClone = R.clone(nestedArray)
console.log(nestedArr[0] === deepCopyWithRamdaClone[0]);
// false -- Deep copy (different reference)
// rdfc

const clone = require('rfdc')() // Returns the deep copy function
clone({a: 37, b: {c: 3700}}) // {a: 37, b: {c: 3700}}
profile
이 블로그의 글은 제 생각을 정리한 글과 인터넷 어딘가에서 배운 것을 정리한 글입니다. 출처는 되도록 남기도록 하겠습니다. 수정 및 건의 오류 등이 있으면 언제든지 댓글 부탁드립니다.

0개의 댓글