How to Deep Copy with jQuery $.extend()

In JavaScript, duplicating complex objects without retaining references to nested properties is a common challenge. A deep copy solves this by recursively duplicating all properties and nested structures, ensuring that the new object is completely detached from the original. This article explains the difference between shallow and deep copies and demonstrates how to implement a deep copy using jQuery's built-in $.extend() method.

Understanding Shallow Copy vs. Deep Copy

When you perform a shallow copy of an object, only the top-level properties are duplicated. If a property value is a reference type (such as an inner object or an array), the copy only duplicates the memory address pointing to that reference. Consequently, modifying a nested object in the copy will inadvertently modify the nested object in the original.

A deep copy recursively duplicates every object and array found within the original structure. Primitive values are copied directly, while nested objects are given completely new allocations in memory. Modifying any level of a deeply copied object will have no effect on the original object.

How to Perform a Deep Copy Using jQuery $.extend()

jQuery provides the $.extend() utility primarily for merging objects. By default, it performs a shallow merge. However, it accepts an optional boolean flag as its first argument to enable deep copying.

Syntax

$.extend( [deep], target, object1 [, objectN ] );
  • deep: A boolean set to true to perform a recursive (deep) copy.
  • target: The destination object that will receive the properties.
  • object1: The source object containing the properties to copy.

The Correct Implementation

To create a deep clone of an object without mutating the original, pass true as the first argument, an empty object literal {} as the target, and your source object as the third argument:

const original = {
  name: "Alice",
  details: {
    age: 30,
    city: "New York"
  }
};

// Perform a deep copy
const clone = $.extend(true, {}, original);

// Mutate the nested property in the clone
clone.details.city = "San Francisco";

console.log(original.details.city); // Output: "New York" (remains unchanged)
console.log(clone.details.city);    // Output: "San Francisco"

If you omit the empty object {} and write $.extend(true, original, ...), the original object itself will be modified because it is treated as the target. Passing {} guarantees that a brand-new object is created and returned.