0
# Lodash Clone
1
2
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.
3
4
## Package Information
5
6
- **Package Name**: lodash
7
- **Package Type**: npm
8
- **Language**: JavaScript
9
- **Installation**: `npm install lodash`
10
11
## Core Imports
12
13
```javascript
14
import { clone, cloneDeep, cloneWith, cloneDeepWith } from "lodash";
15
```
16
17
For CommonJS:
18
19
```javascript
20
const { clone, cloneDeep, cloneWith, cloneDeepWith } = require("lodash");
21
```
22
23
Full lodash import:
24
25
```javascript
26
import _ from "lodash";
27
// Use as _.clone(), _.cloneDeep(), etc.
28
```
29
30
## Basic Usage
31
32
```javascript
33
import { clone, cloneDeep } from "lodash";
34
35
// Shallow clone - shared references for nested objects
36
const original = { a: 1, b: { c: 2 } };
37
const shallow = clone(original);
38
console.log(shallow.b === original.b); // => true
39
40
// Deep clone - completely independent copy
41
const deep = cloneDeep(original);
42
console.log(deep.b === original.b); // => false
43
44
// Works with arrays
45
const arr = [{ name: "Alice" }, { name: "Bob" }];
46
const clonedArr = clone(arr);
47
console.log(clonedArr[0] === arr[0]); // => true (shallow)
48
49
const deepArr = cloneDeep(arr);
50
console.log(deepArr[0] === arr[0]); // => false (deep)
51
```
52
53
## Architecture
54
55
Lodash clone functionality is built around several key architectural components:
56
57
- **Core Engine**: The `baseClone` function serves as the central implementation handling all clone operations with parameters for depth, customization, and circular reference tracking
58
- **Type Routing**: Specialized clone handlers route different JavaScript types to optimized cloning strategies based on their `toStringTag`
59
- **Circular Reference Protection**: A stack-based tracking system prevents infinite recursion when cloning objects with circular references
60
- **Property Preservation**: Special logic preserves important properties like `lastIndex` on RegExp objects, `index` and `input` on RegExp exec results, and constructor relationships
61
- **Customization Layer**: Optional customizer functions allow override of default cloning behavior at any level of the object tree
62
- **Type-Specific Handlers**: Dedicated functions for complex types like ArrayBuffers, typed arrays, Maps, Sets, and Node.js Buffers ensure correct cloning semantics
63
64
## Capabilities
65
66
### Shallow Clone
67
68
Creates a shallow clone of a value where nested objects and arrays are shared between the original and clone.
69
70
```javascript { .api }
71
/**
72
* Creates a shallow clone of `value`.
73
* @param {*} value The value to clone.
74
* @returns {*} Returns the cloned value.
75
*/
76
function clone(value);
77
```
78
79
**Supported Types:**
80
- **Arrays**: Standard arrays and array-like objects
81
- **ArrayBuffers**: Binary data buffers with proper byte copying
82
- **Booleans**: Boolean primitives and Boolean objects
83
- **Dates**: Date objects with preserved time values
84
- **Maps**: Map objects with all key-value pairs preserved
85
- **Numbers**: Number primitives and Number objects
86
- **Objects**: Plain objects and object instances
87
- **RegExp**: Regular expressions with source, flags, and `lastIndex` preserved
88
- **Sets**: Set objects with all values preserved
89
- **Strings**: String primitives and String objects
90
- **Symbols**: Both symbol primitives and Symbol objects
91
- **Typed Arrays**: All typed array types (Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array)
92
- **Arguments Objects**: Cloned as plain objects with length property
93
- **Buffers**: Node.js Buffer objects (when available)
94
95
**Unsupported Types:** Returns empty object `{}` for functions, DOM nodes, WeakMaps, error objects, generators
96
97
**Usage Examples:**
98
99
```javascript
100
// Basic shallow cloning
101
const obj = { a: 1, b: { c: 2 } };
102
const cloned = clone(obj);
103
cloned.a = 10;
104
cloned.b.c = 20;
105
console.log(obj.a); // => 1 (independent)
106
console.log(obj.b.c); // => 20 (shared reference)
107
108
// Array cloning
109
const numbers = [1, 2, 3];
110
const clonedNumbers = clone(numbers);
111
console.log(clonedNumbers); // => [1, 2, 3]
112
113
// Date cloning
114
const date = new Date();
115
const clonedDate = clone(date);
116
console.log(clonedDate instanceof Date); // => true
117
```
118
119
### Shallow Clone with Customizer
120
121
Like clone but accepts a customizer function to produce the cloned value.
122
123
```javascript { .api }
124
/**
125
* This method is like `clone` except that it accepts `customizer` which
126
* is invoked to produce the cloned value.
127
* @param {*} value The value to clone.
128
* @param {Function} [customizer] The function to customize cloning.
129
* @returns {*} Returns the cloned value.
130
*/
131
function cloneWith(value, customizer);
132
```
133
134
**Customizer Function:**
135
- Called with arguments: `(value [, index|key, object, stack])`
136
- Return `undefined` to handle cloning normally
137
- Return any other value to use as the cloned result
138
139
**Usage Examples:**
140
141
```javascript
142
// Custom DOM node cloning
143
function customizer(value) {
144
if (value && value.nodeType === 1) { // Element node
145
return value.cloneNode(false);
146
}
147
}
148
149
const el = cloneWith(document.body, customizer);
150
console.log(el === document.body); // => false
151
console.log(el.nodeName); // => 'BODY'
152
153
// Custom handling for specific types
154
function typeCustomizer(value) {
155
if (typeof value === 'symbol') {
156
return Symbol(value.description);
157
}
158
}
159
160
const obj = { sym: Symbol('test') };
161
const customCloned = cloneWith(obj, typeCustomizer);
162
```
163
164
### Deep Clone
165
166
Creates a deep clone of a value where all nested objects and arrays are recursively cloned.
167
168
```javascript { .api }
169
/**
170
* This method is like `clone` except that it recursively clones `value`.
171
* @param {*} value The value to recursively clone.
172
* @returns {*} Returns the deep cloned value.
173
*/
174
function cloneDeep(value);
175
```
176
177
**Usage Examples:**
178
179
```javascript
180
// Deep object cloning
181
const original = {
182
user: { name: "Alice", profile: { age: 25 } },
183
tags: ["admin", "user"]
184
};
185
186
const deepCloned = cloneDeep(original);
187
deepCloned.user.profile.age = 30;
188
deepCloned.tags.push("moderator");
189
190
console.log(original.user.profile.age); // => 25 (unchanged)
191
console.log(original.tags.length); // => 2 (unchanged)
192
193
// Circular reference handling
194
const circular = { a: 1 };
195
circular.self = circular;
196
const clonedCircular = cloneDeep(circular);
197
console.log(clonedCircular.self === clonedCircular); // => true
198
199
// Complex nested structures with multiple circular references
200
const complex = { data: { items: [] } };
201
complex.data.parent = complex;
202
complex.data.items.push({ ref: complex.data });
203
const clonedComplex = cloneDeep(complex);
204
console.log(clonedComplex.data.parent === clonedComplex); // => true
205
console.log(clonedComplex.data.items[0].ref === clonedComplex.data); // => true
206
```
207
208
### Deep Clone with Customizer
209
210
Like cloneWith but recursively clones the value with customization.
211
212
```javascript { .api }
213
/**
214
* This method is like `cloneWith` except that it recursively clones `value`.
215
* @param {*} value The value to recursively clone.
216
* @param {Function} [customizer] The function to customize cloning.
217
* @returns {*} Returns the deep cloned value.
218
*/
219
function cloneDeepWith(value, customizer);
220
```
221
222
**Usage Examples:**
223
224
```javascript
225
// Custom deep cloning for DOM elements
226
function domCustomizer(value) {
227
if (value && value.nodeType === 1) {
228
return value.cloneNode(true); // Deep clone DOM
229
}
230
}
231
232
const container = cloneDeepWith(document.getElementById('container'), domCustomizer);
233
234
// Custom handling for class instances
235
function classCustomizer(value) {
236
if (value instanceof MyClass) {
237
return new MyClass(value.getData());
238
}
239
}
240
241
const complex = {
242
instance: new MyClass(),
243
nested: { another: new MyClass() }
244
};
245
246
const customDeepCloned = cloneDeepWith(complex, classCustomizer);
247
```
248
249
## Type Definitions
250
251
```javascript { .api }
252
/**
253
* Customizer function for clone operations
254
* @callback Customizer
255
* @param {*} value - The value being cloned
256
* @param {number|string} [index] - The index or key of value
257
* @param {Object} [object] - The parent object of value
258
* @param {Object} [stack] - The stack for tracking circular references
259
* @returns {*} The custom cloned value or undefined for default handling
260
*/
261
262
/**
263
* Cloneable value types supported by lodash clone functions
264
* @typedef {Array|ArrayBuffer|boolean|Date|Map|number|Object|RegExp|Set|string|symbol|TypedArray} CloneableValue
265
*/
266
```
267
268
## Advanced Features
269
270
### Circular Reference Handling
271
272
Lodash clone functions automatically detect and handle circular references to prevent infinite recursion:
273
274
```javascript
275
// Self-referencing object
276
const obj = { name: "parent" };
277
obj.self = obj;
278
const cloned = cloneDeep(obj);
279
console.log(cloned.self === cloned); // => true (maintains circularity)
280
281
// Cross-referencing objects
282
const a = { name: "a" };
283
const b = { name: "b", ref: a };
284
a.ref = b;
285
const clonedA = cloneDeep(a);
286
console.log(clonedA.ref.ref === clonedA); // => true
287
```
288
289
### Property Preservation
290
291
Clone functions preserve important properties and metadata:
292
293
```javascript
294
// RegExp lastIndex preservation
295
const regex = /test/g;
296
regex.lastIndex = 5;
297
const clonedRegex = clone(regex);
298
console.log(clonedRegex.lastIndex); // => 5
299
300
// RegExp exec result properties (index and input)
301
const execResult = /(\w+)/.exec("hello world");
302
execResult.customProp = "added";
303
const clonedResult = clone(execResult);
304
console.log(clonedResult.index); // => 0 (preserved)
305
console.log(clonedResult.input); // => "hello world" (preserved)
306
console.log(clonedResult.customProp); // => "added" (preserved)
307
308
// Array expando properties
309
const arr = [1, 2, 3];
310
arr.customProperty = "custom";
311
const clonedArr = clone(arr);
312
console.log(clonedArr.customProperty); // => "custom"
313
```
314
315
### Buffer Cloning (Node.js)
316
317
In Node.js environments, Buffer objects are properly cloned:
318
319
```javascript
320
// Node.js Buffer handling
321
const buffer = Buffer.from("hello", "utf8");
322
const clonedBuffer = clone(buffer);
323
console.log(Buffer.isBuffer(clonedBuffer)); // => true
324
console.log(clonedBuffer.toString()); // => "hello"
325
console.log(clonedBuffer === buffer); // => false (different instances)
326
```
327
328
## Error Handling
329
330
Clone functions handle edge cases gracefully:
331
332
- **Uncloneable values** (functions, DOM nodes, WeakMaps, error objects): Return empty objects `{}`
333
- **Null/undefined**: Return as-is
334
- **Primitives**: Return as-is (numbers, strings, booleans)
335
- **Circular references**: Detected and handled properly in deep clone operations
336
- **Invalid customizer**: Ignored if not a function, falls back to default behavior
337
338
## Performance Notes
339
340
- **Shallow cloning** is faster and uses less memory
341
- **Deep cloning** is more expensive but provides complete independence
342
- **Customizers** add overhead but provide flexibility
343
- Consider using shallow clone when nested object sharing is acceptable
344
- Use deep clone when complete isolation is required
345
346
## Common Patterns
347
348
```javascript
349
// State management (shallow clone for immutability)
350
const newState = { ...state, updates: clone(state.updates) };
351
352
// API response processing (deep clone for data manipulation)
353
const processedData = cloneDeep(apiResponse);
354
processData(processedData); // Safe to mutate
355
356
// Configuration merging with custom handling
357
const config = cloneDeepWith(defaultConfig, (value) => {
358
if (Array.isArray(value)) {
359
return [...value]; // Custom array handling
360
}
361
});
362
```