Lodash _.assignWith() method

Beginner
⏱️ 7 min read
📚 Updated: May 2026
🎯 3 Code examples
🚀 3 Try-it labs
Lodash

What you’ll learn

  • How _.assignWith(object, ...sources, customizer) layers _.assign with a per-key decision callback.
  • The customizer signature (objValue, srcValue, key, object, source) and the undefined fallback rule.
  • Why this stays on own string keys—and when to prefer _.assignInWith or _.mergeWith.
  • Try each example in the editor (?tryit=1, 2, 3) with Lodash from a CDN.

Prerequisites

Read _.assign() first for the shared shallow/mutating semantics; this page focuses on the customizer.

  • Callbacks: the customizer is a plain function called per key—treat undefined returns as “defer to the default”.
  • Own vs inherited: know why you might want to ignore prototype data (mostly: predictability when sources are class instances).

Overview

_.assignWith is _.assign plus a per-key callback. For every key Lodash would otherwise copy, it asks the customizer for a final value first. Return undefined and Lodash uses the incoming srcValue; return anything else and you decide.

Per-key control

Sum, multiply, prefer the larger value, or keep the existing one—decide independently for each key.

undefined = fall through

A single rule keeps the customizer terse: opt out of a key by returning undefined and the default behavior applies.

Own keys only

Prototype-defined string keys are skipped—reach for _.assignInWith when you do want inherited keys.

Syntax

javascript
_.assignWith(object, [...sources], [customizer])
//
// customizer(objValue, srcValue, key, object, source) => any
  • object: destination object; mutated in place.
  • sources: zero or more source objects; only own enumerable string keys are visited, left to right.
  • customizer: last argument; return undefined to accept the source value, anything else to override.
  • Returns: the (now-mutated) destination object.
  • Skipped: inherited keys (use _.assignInWith), symbol keys, non-enumerable properties, nested depth (use _.mergeWith).
1

Combine numeric values across sources

Sum the destination’s current value with the incoming one when both are numbers; let everything else fall through with undefined.

javascript
import assignWith from "lodash/assignWith";

const target = { a: 1, b: 2 };
const source1 = { b: 3, c: 4 };
const source2 = { d: 5 };

function sumNumbers(objValue, srcValue) {
  if (typeof objValue === "number" && typeof srcValue === "number") {
    return objValue + srcValue;
  }
  // undefined -> srcValue wins as usual
}

assignWith(target, source1, source2, sumNumbers);
// target -> { a: 1, b: 5, c: 4, d: 5 }
Try it Yourself
2

Per-key “take the larger” rule

For a specific key ("priority") keep the maximum across destination and source. Other keys keep their default left-to-right behavior.

javascript
import assignWith from "lodash/assignWith";

const current = { priority: 2, status: "idle" };
const incoming = { priority: 5, status: "active" };

function takeMaxPriority(objValue, srcValue, key) {
  if (key === "priority") {
    return Math.max(objValue, srcValue);
  }
}

assignWith(current, incoming, takeMaxPriority);
// current -> { priority: 5, status: "active" }
Try it Yourself
3

Own keys only (vs assignInWith)

Inherited keys are not visited—the customizer never runs for them. Compare against _.assignInWith, where the same callback would fire for both own and inherited keys.

javascript
import assignWith from "lodash/assignWith";
import assignInWith from "lodash/assignInWith";

function Source() {
  this.own = "instance";
}
Source.prototype.inherited = "prototype";

const seenW = [];
const seenInW = [];
assignWith({},   new Source(), function (o, s, k) { seenW.push(k);   });
assignInWith({}, new Source(), function (o, s, k) { seenInW.push(k); });

// seenW   -> ["own"]
// seenInW -> ["own", "inherited"]
Try it Yourself

📋 _.assignWith vs _.assignInWith vs _.mergeWith

Topic_.assignWith_.assignInWith_.mergeWith
Customizer signature(objValue, srcValue, key, object, source)SameSame, plus stack for recursion
Own keysYesYesYes
Inherited keysNoYesNo
DepthShallowShallowRecursive
Aliases_.extendWith
Typical usePlain objects with per-key rulesClass instances with per-key rulesNested configs with per-key rules

If the sources are plain object literals, _.assignWith is the smallest tool that does the job. Reach for siblings when the source shape forces you to.

Pitfalls to avoid

Customizer

Forgetting the undefined fallback

A customizer that always returns a value (even null or empty string) overwrites every key. Return undefined for keys you want to leave to the default rule.

Depth

Recursing inside the customizer

It’s tempting to call _.assignWith inside itself for nested values—don’t. Use _.mergeWith, which handles recursion natively.

Mutation

Destination is written in place

Pass {} as the first argument when callers share a reference and you need a fresh object.

❓ FAQ

Same customizer signature and shallow shape. _.assignWith stays on own enumerable string keys; _.assignInWith also walks the prototype chain. Pick assignWith when you don't want surprise keys from inherited sources.
Five arguments: (objValue, srcValue, key, object, source). objValue is the current destination value, srcValue is the incoming one, key is the property name, object is the destination, source is the current source object.
Lodash falls back to the source value (srcValue), the same precedence rule _.assign uses. Return any non-undefined value to override per key.
Yes. The first argument is written in place and returned. Pass {} as the destination when you need a fresh object and want to leave inputs untouched.
No. Even with a customizer, the walk is one level deep. For nested combination use _.merge (no customizer) or _.mergeWith (customizer + recursion).
Use import assignWith from "lodash/assignWith"; for ESM or const assignWith = require('lodash/assignWith') in CommonJS.

Summary

Did you know?

_.assignWith shares its customizer signature (objValue, srcValue, key, object, source) with _.assignInWith and _.mergeWith—only the set of keys visited and the depth differ. Pick by what kind of source you have, not by what the customizer looks like.

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

6 people found this page helpful