liveBook · Manning

Deep copy

As explained in Grokking Simplicity

A deep copy recursively duplicates a data structure and all nested objects and arrays so that no structural parts are shared with the original.

A deep copy recursively duplicates every level of a nested structure. Unlike a shallow copy, it shares no nested objects or arrays with the original, protecting immutable data from mutating code. section 7.5 section 7.9

Use deep copying at the boundaries of an immutable safe zone:

  • Copy immutable data deeply before passing it to code that may mutate it. section 7.5
  • Copy data deeply immediately after receiving it from code that may have mutated it. section 7.5
  • Prefer copy-on-write for data under your control; deep copies are more expensive because they duplicate everything. section 7.8 section 7.9

Protecting a shopping cart

Before calling a mutating black_friday_promotion() function, create cart_copy with deepCopy(shopping_cart). After the function returns, deep-copy cart_copy again before treating the result as immutable. This copy-before-and-after pattern prevents the function from changing the original cart or retaining a mutable reference into your code. section 7.4

function deepCopy(thing) {
    if(Array.isArray(thing)) {
        var copy = [];
        for(var i = 0; i < thing.length; i++)
            copy.push(deepCopy(thing[i])); #1
        return copy;
    } else if (thing === null) {
        return null;
    } else if(typeof thing === "object") {
        var copy = {};
        var keys = Object.keys(thing);
        for(var i = 0; i < keys.length; i++) {
            var key = keys[i];
            copy[key] = deepCopy(thing[key]); #1
        }
        return copy;
    } else {
        return thing; #2
    }
}

The teaching implementation handles arrays and objects recursively, returns null unchanged, and leaves JSON-legal primitive values unchanged; it is an outline rather than production-ready JavaScript. section 7.10

How Grokking Simplicity covers it

How deep it goes
Defines recursive structural duplication and compares its cost with shallow copying, but defers a robust JavaScript implementation.
Examples
Uses a shopping cart, web API JSON exchanges, and Erlang or Elixir process messages as defensive-copying examples.
What it assumes
Assumes familiarity with immutable data and copy-on-write while teaching defensive copying for code that does not follow that discipline.
What you can do after
Apply it via Lodash’s _.cloneDeep() when robust JavaScript deep copying is required.
How it connects
Connects defensive copying with immutability, copy-on-write, shallow copying, untrusted code, and shared-nothing architecture.

Also explained in

Compare how 5 books explain deep copy →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Grokking Simplicity. The section links point to the parts of the book it draws on.