Lodash _.cloneDeepWith() method
What you’ll learn
- How
_.cloneDeepWith(value, customizer)deep-clones while letting you override specific nodes. - When to return a replacement value versus
undefinedfor default cloning. - How this differs from _.cloneDeep() and shallow _.cloneWith().
- Practical patterns for functions, classes, or application-specific objects.
Prerequisites
Read _.cloneDeep() first so the recursive cloning baseline is clear.
- You understand JavaScript references and nested object graphs.
- You can run snippets in Node or open Try-it labs in the browser.
Overview
_.cloneDeepWith is cloneDeep plus a per-node hook. Use it when some nested values should not use default cloning (for example shared functions, markers, or wrapped instances).
Per-node control
Inspect each visited value and decide whether to substitute or defer to Lodash.
undefined means default
Return nothing to keep normal recursive cloning for that branch.
Power with cost
Customizers add CPU work per node—keep logic small and predictable.
Syntax
_.cloneDeepWith(value, [customizer]) - value: the root value to clone deeply.
- customizer: invoked for each node; return a replacement or
undefinedfor default cloning. - Returns: the cloned value produced by the merge of defaults and your overrides.
Reuse function references
Return the same function instance instead of letting Lodash walk it as an object.
import cloneDeepWith from "lodash/cloneDeepWith";
var id = function (x) { return x; };
var source = { scale: 2, fn: id };
var copy = cloneDeepWith(source, function (value) {
if (typeof value === "function") {
return value;
}
});
console.log(copy.fn === source.fn); // true Replace a nested leaf
Return an explicit clone for a nested object while other fields use defaults.
import cloneDeepWith from "lodash/cloneDeepWith";
var source = {
label: "root",
node: { id: 1, tag: "leaf" }
};
var copy = cloneDeepWith(source, function (value, key) {
if (key === "node" && value && typeof value === "object") {
return { id: value.id, tag: value.tag.toUpperCase() };
}
});
console.log(copy.node.tag); // "LEAF" Fallback to default cloning
Return nothing for primitives so Lodash keeps normal deep clone behavior.
import cloneDeepWith from "lodash/cloneDeepWith";
var source = { a: 1, b: { c: 2 } };
var copy = cloneDeepWith(source, function (value) {
if (typeof value === "number" && value === 1) {
return 100; // override this leaf
}
// undefined → lodash default for everything else
});
console.log(copy.a, copy.b.c); 📋 cloneDeepWith vs related APIs
| Method | Depth | Customizer |
|---|---|---|
_.cloneDeepWith(value, fn) | Deep | Yes, per node |
_.cloneDeep(value) | Deep | No |
_.cloneWith(value, fn) | Shallow | Yes, top level |
Pitfalls to avoid
Heavy customizers
The function runs often while traversing large trees—avoid expensive work per call.
Wrong key checks
Customizer keys differ for arrays versus objects; verify behavior on sample data.
Accidental shared refs
Returning the original nested object keeps aliasing—only do this intentionally.
❓ FAQ
Summary
- Purpose: deep clone with selective overrides via
customizer. - Rule: return a value to substitute a node; return
undefinedfor default cloning. - Next: Lodash _.cloneWith().
Returning undefined from the customizer tells Lodash to apply its default cloning logic for that node.
6 people found this page helpful
