or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

index.mddocs/

Lodash Clone

Lodash Clone provides comprehensive cloning functionality for JavaScript values, supporting both shallow and deep cloning operations with customization options. Part of the Lodash utility library, these functions handle a wide range of JavaScript types including arrays, objects, primitives, dates, maps, sets, regular expressions, and more.

Package Information

  • Package Name: lodash
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install lodash

Core Imports

import { clone, cloneDeep, cloneWith, cloneDeepWith } from "lodash";

For CommonJS:

const { clone, cloneDeep, cloneWith, cloneDeepWith } = require("lodash");

Full lodash import:

import _ from "lodash";
// Use as _.clone(), _.cloneDeep(), etc.

Basic Usage

import { clone, cloneDeep } from "lodash";

// Shallow clone - shared references for nested objects
const original = { a: 1, b: { c: 2 } };
const shallow = clone(original);
console.log(shallow.b === original.b); // => true

// Deep clone - completely independent copy
const deep = cloneDeep(original);
console.log(deep.b === original.b); // => false

// Works with arrays
const arr = [{ name: "Alice" }, { name: "Bob" }];
const clonedArr = clone(arr);
console.log(clonedArr[0] === arr[0]); // => true (shallow)

const deepArr = cloneDeep(arr);
console.log(deepArr[0] === arr[0]); // => false (deep)

Architecture

Lodash clone functionality is built around several key architectural components:

  • Core Engine: The baseClone function serves as the central implementation handling all clone operations with parameters for depth, customization, and circular reference tracking
  • Type Routing: Specialized clone handlers route different JavaScript types to optimized cloning strategies based on their toStringTag
  • Circular Reference Protection: A stack-based tracking system prevents infinite recursion when cloning objects with circular references
  • Property Preservation: Special logic preserves important properties like lastIndex on RegExp objects, index and input on RegExp exec results, and constructor relationships
  • Customization Layer: Optional customizer functions allow override of default cloning behavior at any level of the object tree
  • Type-Specific Handlers: Dedicated functions for complex types like ArrayBuffers, typed arrays, Maps, Sets, and Node.js Buffers ensure correct cloning semantics

Capabilities

Shallow Clone

Creates a shallow clone of a value where nested objects and arrays are shared between the original and clone.

/**
 * Creates a shallow clone of `value`.
 * @param {*} value The value to clone.
 * @returns {*} Returns the cloned value.
 */
function clone(value);

Supported Types:

  • Arrays: Standard arrays and array-like objects
  • ArrayBuffers: Binary data buffers with proper byte copying
  • Booleans: Boolean primitives and Boolean objects
  • Dates: Date objects with preserved time values
  • Maps: Map objects with all key-value pairs preserved
  • Numbers: Number primitives and Number objects
  • Objects: Plain objects and object instances
  • RegExp: Regular expressions with source, flags, and lastIndex preserved
  • Sets: Set objects with all values preserved
  • Strings: String primitives and String objects
  • Symbols: Both symbol primitives and Symbol objects
  • Typed Arrays: All typed array types (Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array)
  • Arguments Objects: Cloned as plain objects with length property
  • Buffers: Node.js Buffer objects (when available)

Unsupported Types: Returns empty object {} for functions, DOM nodes, WeakMaps, error objects, generators

Usage Examples:

// Basic shallow cloning
const obj = { a: 1, b: { c: 2 } };
const cloned = clone(obj);
cloned.a = 10;
cloned.b.c = 20;
console.log(obj.a); // => 1 (independent)
console.log(obj.b.c); // => 20 (shared reference)

// Array cloning
const numbers = [1, 2, 3];
const clonedNumbers = clone(numbers);
console.log(clonedNumbers); // => [1, 2, 3]

// Date cloning
const date = new Date();
const clonedDate = clone(date);
console.log(clonedDate instanceof Date); // => true

Shallow Clone with Customizer

Like clone but accepts a customizer function to produce the cloned value.

/**
 * This method is like `clone` except that it accepts `customizer` which
 * is invoked to produce the cloned value.
 * @param {*} value The value to clone.
 * @param {Function} [customizer] The function to customize cloning.
 * @returns {*} Returns the cloned value.
 */
function cloneWith(value, customizer);

Customizer Function:

  • Called with arguments: (value [, index|key, object, stack])
  • Return undefined to handle cloning normally
  • Return any other value to use as the cloned result

Usage Examples:

// Custom DOM node cloning
function customizer(value) {
  if (value && value.nodeType === 1) { // Element node
    return value.cloneNode(false);
  }
}

const el = cloneWith(document.body, customizer);
console.log(el === document.body); // => false
console.log(el.nodeName); // => 'BODY'

// Custom handling for specific types
function typeCustomizer(value) {
  if (typeof value === 'symbol') {
    return Symbol(value.description);
  }
}

const obj = { sym: Symbol('test') };
const customCloned = cloneWith(obj, typeCustomizer);

Deep Clone

Creates a deep clone of a value where all nested objects and arrays are recursively cloned.

/**
 * This method is like `clone` except that it recursively clones `value`.
 * @param {*} value The value to recursively clone.
 * @returns {*} Returns the deep cloned value.
 */
function cloneDeep(value);

Usage Examples:

// Deep object cloning
const original = {
  user: { name: "Alice", profile: { age: 25 } },
  tags: ["admin", "user"]
};

const deepCloned = cloneDeep(original);
deepCloned.user.profile.age = 30;
deepCloned.tags.push("moderator");

console.log(original.user.profile.age); // => 25 (unchanged)
console.log(original.tags.length); // => 2 (unchanged)

// Circular reference handling
const circular = { a: 1 };
circular.self = circular;
const clonedCircular = cloneDeep(circular);
console.log(clonedCircular.self === clonedCircular); // => true

// Complex nested structures with multiple circular references
const complex = { data: { items: [] } };
complex.data.parent = complex;
complex.data.items.push({ ref: complex.data });
const clonedComplex = cloneDeep(complex);
console.log(clonedComplex.data.parent === clonedComplex); // => true
console.log(clonedComplex.data.items[0].ref === clonedComplex.data); // => true

Deep Clone with Customizer

Like cloneWith but recursively clones the value with customization.

/**
 * This method is like `cloneWith` except that it recursively clones `value`.
 * @param {*} value The value to recursively clone.
 * @param {Function} [customizer] The function to customize cloning.
 * @returns {*} Returns the deep cloned value.
 */
function cloneDeepWith(value, customizer);

Usage Examples:

// Custom deep cloning for DOM elements
function domCustomizer(value) {
  if (value && value.nodeType === 1) {
    return value.cloneNode(true); // Deep clone DOM
  }
}

const container = cloneDeepWith(document.getElementById('container'), domCustomizer);

// Custom handling for class instances
function classCustomizer(value) {
  if (value instanceof MyClass) {
    return new MyClass(value.getData());
  }
}

const complex = {
  instance: new MyClass(),
  nested: { another: new MyClass() }
};

const customDeepCloned = cloneDeepWith(complex, classCustomizer);

Type Definitions

/**
 * Customizer function for clone operations
 * @callback Customizer
 * @param {*} value - The value being cloned
 * @param {number|string} [index] - The index or key of value
 * @param {Object} [object] - The parent object of value  
 * @param {Object} [stack] - The stack for tracking circular references
 * @returns {*} The custom cloned value or undefined for default handling
 */

/**
 * Cloneable value types supported by lodash clone functions
 * @typedef {Array|ArrayBuffer|boolean|Date|Map|number|Object|RegExp|Set|string|symbol|TypedArray} CloneableValue
 */

Advanced Features

Circular Reference Handling

Lodash clone functions automatically detect and handle circular references to prevent infinite recursion:

// Self-referencing object
const obj = { name: "parent" };
obj.self = obj;
const cloned = cloneDeep(obj);
console.log(cloned.self === cloned); // => true (maintains circularity)

// Cross-referencing objects
const a = { name: "a" };
const b = { name: "b", ref: a };
a.ref = b;
const clonedA = cloneDeep(a);
console.log(clonedA.ref.ref === clonedA); // => true

Property Preservation

Clone functions preserve important properties and metadata:

// RegExp lastIndex preservation
const regex = /test/g;
regex.lastIndex = 5;
const clonedRegex = clone(regex);
console.log(clonedRegex.lastIndex); // => 5

// RegExp exec result properties (index and input)
const execResult = /(\w+)/.exec("hello world");
execResult.customProp = "added";
const clonedResult = clone(execResult);
console.log(clonedResult.index); // => 0 (preserved)
console.log(clonedResult.input); // => "hello world" (preserved)
console.log(clonedResult.customProp); // => "added" (preserved)

// Array expando properties
const arr = [1, 2, 3];
arr.customProperty = "custom";
const clonedArr = clone(arr);
console.log(clonedArr.customProperty); // => "custom"

Buffer Cloning (Node.js)

In Node.js environments, Buffer objects are properly cloned:

// Node.js Buffer handling
const buffer = Buffer.from("hello", "utf8");
const clonedBuffer = clone(buffer);
console.log(Buffer.isBuffer(clonedBuffer)); // => true
console.log(clonedBuffer.toString()); // => "hello"
console.log(clonedBuffer === buffer); // => false (different instances)

Error Handling

Clone functions handle edge cases gracefully:

  • Uncloneable values (functions, DOM nodes, WeakMaps, error objects): Return empty objects {}
  • Null/undefined: Return as-is
  • Primitives: Return as-is (numbers, strings, booleans)
  • Circular references: Detected and handled properly in deep clone operations
  • Invalid customizer: Ignored if not a function, falls back to default behavior

Performance Notes

  • Shallow cloning is faster and uses less memory
  • Deep cloning is more expensive but provides complete independence
  • Customizers add overhead but provide flexibility
  • Consider using shallow clone when nested object sharing is acceptable
  • Use deep clone when complete isolation is required

Common Patterns

// State management (shallow clone for immutability)
const newState = { ...state, updates: clone(state.updates) };

// API response processing (deep clone for data manipulation)
const processedData = cloneDeep(apiResponse);
processData(processedData); // Safe to mutate

// Configuration merging with custom handling
const config = cloneDeepWith(defaultConfig, (value) => {
  if (Array.isArray(value)) {
    return [...value]; // Custom array handling
  }
});