Shallow copy oznacza kopię płytką. Oznacza to, że skopiowano jedynie sam obiekt, ale referencje wewnątrz niego wskazują na te same wartości, co referencje wewnątrz oryginału.
Zawartość obiektów i tablice można kopiować na przykład za pomocą spread operatora ...
.
const obj = {a: {}, b: {}}; const copyObj = {...obj}; const arr = [{}, {}]; const copyArr = [...arr]; console.info(obj === copyObj, obj.a === copyObj.a, obj.b === copyObj.b); // false, true, true console.info(arr === copyArr, arr[0] === copyArr[0], arr[1] === copyArr[1]); // false, true, true
Zanim wprowadzono spread operator w ES2018, możliwe było dokonywanie kopii płytkich za pomocą Object.assign
:
const obj = { a: 1 }; const copyObj = Object.assign({}, obj); console.info(obj === copyObj, obj.a === copyObj.a, obj.b === copyObj.b); // false, true, true
Deep copy oznacza kopię głęboką. W tym przypadku kopiowane są wszystkie wartości potomne, a także ich wartości. Istnieje kilka sposobów zbudowania deep copy.
Jednym z nich jest serializacja obiektu do stringa, a następnie deserializacja do obiektu:
const obj = {a: {}, b: {}}; const copyObj = JSON.parse(JSON.stringify(obj)); const arr = [{}, {}]; const copyArr = JSON.parse(JSON.stringify(arr)); console.info(obj === copyObj, obj.a === copyObj.a, obj.b === copyObj.b); // false, false, false console.info(arr === copyArr, arr[0] === copyArr[0], arr[1] === copyArr[1]); // false, false, false
To rozwiązanie dobrze nadaje się do kopiowania wartości prostych - bez prototypów, funkcji itp.
Inną metodą jest skorzystanie z funkcji structuredClone
:
const obj = {a: {}, b: {}}; const copyObj = structuredClone(obj); const arr = [{}, {}]; const copyArr = structuredClone(arr); console.info(obj === copyObj, obj.a === copyObj.a, obj.b === copyObj.b); // false, false, false console.info(arr === copyArr, arr[0] === copyArr[0], arr[1] === copyArr[1]); // false, false, false