Lodash _.get() method
What you’ll learn
- How
_.get(object, path, [defaultValue])safely reads nested values, even when intermediate segments are missing. - The three path formats: dotted string, bracket notation, and array of segments—and when each is required.
- Why
null,0, andfalseare not replaced by the default value. - When to reach for native optional chaining (
?.) instead.
Prerequisites
Comfortable with property access (obj.a.b) and basic JSON shapes. Familiarity with optional chaining helps but isn’t required.
- undefined vs. nullish: the default only fires for
undefined.nullsurvives. - Dynamic vs. static paths: use
_.getwhen the path is computed at runtime; otherwise consider native?.. - Array form for tricky keys: keys containing dots or brackets require the array path form.
Overview
_.get resolves a path segment by segment. If any segment along the way is null or undefined, the traversal stops and the default value (or undefined) is returned—no thrown TypeError. It accepts the object as null or undefined too, which makes it safe for partial API responses.
Crash-free reads
No Cannot read properties of undefined—missing segments produce the default instead.
Three path formats
Dotted string, bracket notation, or an array of segments. Mix them freely.
Default only for undefined
null, 0, "", false all pass through unchanged.
Syntax
_.get(object, path, [defaultValue]) - object: source to read from. May be
nullorundefined. - path: a string (
"a.b[0].c") or an array (["a", "b", 0, "c"]). - defaultValue (optional): returned when the resolved value is
undefined. - Returns: the resolved value, or
defaultValue, orundefined.
Safe nested reads with a default
The classic use case: pull a deeply-nested value, falling back to a sensible default when any intermediate segment is missing.
import get from "lodash/get";
const profile = {
user: {
details: { name: "John Doe", age: 30 },
preferences: { theme: "dark" }
}
};
get(profile, "user.details.name", "Unknown");
// -> "John Doe"
get(profile, "user.contact.email", "no-email@example.com");
// -> "no-email@example.com"
// user.contact is undefined, so the default is used.
get(profile, "user.details.age");
// -> 30 (no default needed) Three path formats & array indexing
Dotted string, bracket string, and array path all describe the same traversal—but only the array form is safe when a key contains dots or special characters.
import get from "lodash/get";
const data = {
users: [
{ id: 1, name: "Ada" },
{ id: 2, name: "Linus" }
],
"x.y": { z: 42 } // literal key contains a dot
};
get(data, "users[0].name"); // -> "Ada" (bracket notation)
get(data, "users.1.name"); // -> "Linus" (dotted, numeric segment)
get(data, ["users", 1, "id"]);// -> 2 (array path, numeric index)
get(data, "x.y.z"); // -> undefined
// ^ wrong: splits into ["x", "y", "z"]; "x" doesn't exist.
get(data, ["x.y", "z"]); // -> 42
// ^ correct: array form preserves the dotted key literally. null survives the default
A subtle one: the default fires only for undefined. If the API explicitly returned null, you keep null. Same goes for 0, "", and false.
import get from "lodash/get";
const flags = {
email: null,
retries: 0,
notes: "",
archived: false
};
get(flags, "email", "default@example.com");
// -> null (default IS NOT used)
get(flags, "retries", 3); // -> 0
get(flags, "notes", "n/a"); // -> ""
get(flags, "archived", true); // -> false
get(flags, "missing", "default@example.com");
// -> "default@example.com" (path is undefined, default kicks in) 📋 _.get vs ?. vs _.at
| Topic | _.get | Optional chaining ?. | _.at |
|---|---|---|---|
| Crash-safe | Yes | Yes | Yes |
| Dynamic path | Yes (string or array) | No (static literal) | Yes (array of paths) |
| Default value | For undefined only | Use ?? manually | No default; returns an array |
| Multiple paths | One per call | One per expression | Many at once |
| Runtime cost | Function call | Zero (native) | Function call + allocation |
Use optional chaining for known shapes and hot paths. Use _.get when the path is data-driven or you want the default in one shot. Use _.at when you need several values at once.
Pitfalls to avoid
null blocks the default
The default only fires for undefined. To also replace null, combine with ??: _.get(obj, "x", fallback) ?? fallback.
Dotted keys break string paths
If a key literally contains a dot, the string form splits it. Use an array path: ["x.y", "z"].
Don’t feed user input to _.get blindly
Dynamic paths sourced from a query string can read __proto__ or other internals. Validate against an allow-list.
Costlier than ?.
String parsing and a function call per read add up. In hot loops with a known shape, prefer native optional chaining.
❓ FAQ
Summary
- Purpose: safely read a value at a path, returning a default when the path is missing.
- Remember: default fires only for
undefined;null/0/false/""survive. Use array paths for keys with dots. - Next: Lodash _.has(), _.set(), or the official Lodash docs for _.get.
The defaultValue argument is only used when the path resolves to undefined. A path that resolves to null, 0, false, or "" keeps that value—Lodash will not substitute the default.
6 people found this page helpful
