shallow copy
deep copy
어느 언어에나 shallow copy, deep copy에 대한 이야기는 있을 것으로 생각된다.
JS에서 어떤 객체를 copy하는 경우
JS의 객체는 Primitive value에 대해서는 deep copy를 한다.
이외의 다른 객체는 shallow copy를 한다는 것이 요점이다.
Primitive 객체가 아닌 객체에 대해 shallow copy가 발생한다 예를 들면
copy를 변경했는데 ary까지 같이 변경이 되었다.
이는 ary, copy가 같은 변수를 참조하고 있다는 것이다.
아래의 이미지를 하나 더 보자
ary 배열에 객체를 각각 담아 선언하고
prototype을 통해 copy를 했다
copy를 변경하고 ary를 다시 호출했더니 변경되지 않았다.
copy와 ary는
이렇게 deep copy가 되어 서로 전혀 관계가 없는 상태가 되었을까?
다른걸 시도해보자
ary[0].a 객체를 변경하고 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}}