Lodash cloneWith: Override Default Cloning Behavior
Lodash's _.cloneWith method allows developers to
customize how JavaScript objects and values are cloned by accepting a
dedicated customizer callback. This article explains how
_.cloneWith operates, detailing the mechanism it uses to
intercept the cloning process, how it delegates back to Lodash's default
shallow copy behavior, and how to apply it in real-world scenarios.
Understanding
_.cloneWith
The _.cloneWith method behaves similarly to
_.clone, performing a shallow copy of an input value.
However, it introduces a second argument: a customizer function. This
function can intercept the cloning of the value and dictate the exact
cloned output.
The syntax for the method is:
_.cloneWith(value, [customizer])The Customizer Function Mechanism
The customizer function is invoked to produce the cloned value. It receives several arguments depending on the context:
value: The value currently being cloned.key: The key or index of the property being cloned (if cloning a property).object: The parent object containing the property.stack: An internal Lodash structure tracking circular references.
The core mechanism for overriding default cloning relies entirely on the return value of the customizer function:
- Explicit Return Value: If the customizer returns
any value other than
undefined,_.cloneWithassigns that returned value directly as the clone result. This allows you to replace values, instantiate new types, or retain references as needed. - Returning
undefined: If the customizer returnsundefined(either explicitly or by having no return statement), Lodash assumes no override is intended and falls back to its standard shallow cloning algorithm.
Practical Implementation
The following example demonstrates overriding the cloning behavior for a specific property type while allowing default cloning for all other properties:
const _ = require('lodash');
function customizer(value, key) {
// Override: do not clone functions; return a wrapped execution or a placeholder
if (typeof value === 'function') {
return value.bind({});
}
// Override: transform or handle a specific key
if (key === 'timestamp') {
return new Date();
}
// Fall back to default cloning for everything else
return undefined;
}
const original = {
id: 101,
name: 'Sample Item',
timestamp: new Date('2020-01-01'),
run: function() { return 'executed'; }
};
const cloned = _.cloneWith(original, customizer);
console.log(cloned.id); // 101 (handled by default cloning)
console.log(cloned.timestamp); // Current date (handled by customizer)Shallow vs. Deep Customization
It is important to note that _.cloneWith operates as a
shallow clone. The customizer function is only called for the top-level
value and its immediate properties.
If an application requires recursive traversal of nested objects or
arrays where the customizer is invoked at every depth level, Lodash
provides _.cloneDeepWith instead. Both methods adhere to
the same customizer contract: returning a defined value overrides the
clone, while returning undefined defers to standard cloning
logic.