Safe Nested Access in JavaScript: Lodash _.get vs Optional Chaining
Use Lodash _.get to read deeply nested properties without TypeErrors, but know when native optional chaining is the lighter choice.
18 Jul 2026, 09:24 UTC

A missing profile crashes the page
You render a user dashboard and the browser throws TypeError: Cannot read properties of undefined (reading 'twitter'). The API returned a user object, but profile.social is missing. Reaching into nested data with dot notation assumes every link in the chain exists, which frontend and integration code often cannot guarantee.
The practical takeaway: Lodash 4.x's _.get(object, path, defaultValue) reads nested properties safely and returns a fallback when any segment is null or undefined. Native optional chaining handles many of the same cases without a dependency, but _.get can be cleaner for array indices and shared defaults. The right choice depends on bundle size, team readability, and whether a silent default hides a real data problem.
How _.get resolves a path
_.get accepts an object, a path string or array, and an optional default. It walks each segment. If it hits null or undefined before the end, it returns the default instead of throwing.
The path supports dot notation and bracket notation, including array indices:
import get from 'lodash/get';
const user = {
profile: {
social: { twitter: '@dev' }
}
};
const handle = get(user, 'profile.social.twitter', '@anonymous');
// '@anonymous' when profile.social is missing
const firstId = get(data, 'items[0].id', 'unknown');
Array paths such as ['items', 0, 'id'] work the same way. The default applies when resolution yields undefined, so an explicitly undefined terminal value may look identical to a missing path at some call sites.
Native optional chaining often does the job
Modern JavaScript offers optional chaining (?.) and nullish coalescing (??):
const handle = user?.profile?.social?.twitter ?? '@anonymous';
This reads naturally and adds no bundle weight. Use it when the structure is fixed and you only need one or two lookups. _.get tends to win when you access many fields with the same default, when paths are built dynamically as strings, or when array indices make the optional-chaining chain verbose.
| Situation | Better fit | Why |
|---|---|---|
| One-off deep access in application code | Optional chaining | No dependency, familiar syntax |
| Repeated access with a shared default | _.get |
Single default argument, less repetition |
| Dynamic path strings from configuration | _.get |
Accepts path strings and arrays directly |
| Client bundle size is critical | Optional chaining or lodash/get |
Avoids importing the full Lodash library |
Import only what you ship
Importing from the main lodash package can pull the entire library into your bundle unless your build tool uses Lodash-specific tree-shaking. Prefer the modular entry point:
import get from 'lodash/get';
// or
import { get } from 'lodash-es';
Verify your installed major version before relying on this behavior. Run this in your project root:
node -e "console.log(require('lodash/package.json').version)"
Expected output: a version string starting with 4. No special permissions are required. If the package is missing, install it first; if it is a 3.x or pre-4 release, behavior may differ.
Verify fallback behavior before you deploy
Run this in a Node REPL to confirm default fallback and array index access:
node -e "
const get = require('lodash/get');
console.log(get({ a: { b: null } }, 'a.b.c', 'fallback'));
console.log(get({ a: [{ b: 2 }] }, 'a[0].b', 'fallback'));
"
Expected: the first call returns 'fallback' because b is null; the second returns 2. Compare against obj?.a?.b?.c ?? 'fallback' across missing, null, and present values to confirm they match for your data shapes.
The risk: silent defaults can hide contract violations
A missing property sometimes means the API changed or the data model is broken, not that the value is optional. Returning '@anonymous' can make a bug harder to trace than an immediate crash. Use _.get when the default is genuinely meaningful. When absence signals an error, validate the schema up front or let the application fail loudly.
Decide and ship
Check your Lodash version, test _.get against the native equivalent with real payloads, and import from lodash/get or lodash-es to control bundle size. If a missing value should alert your team, pair the lookup with validation instead of a silent fallback.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.