frontend
Lodash get() Implementation in JavaScript
January 24, 2026
Lodash get() Implementation in JavaScript
Overview
Lodash's get() function safely retrieves nested object properties using a path string or array. It returns a default value if the path doesn't exist, preventing errors when accessing deeply nested properties that might be undefined.
Basic Implementation
//Lodash get()
let obj = {
user: {
name: "Ashish",
address: {
place: "Bengaluru",
},
phone: [{ primary: 123456789 }, { secondary: 444444444 }],
},
};
function lodashGet(object, path, defaultValue) {
if (object === undefined || object === null) {
return defaultValue;
}
const keys = !Array.isArray(path)
? path.replaceAll("[", ".").replaceAll("]", "").split(".")
: path;
let current = object;
for (let key of keys) {
if (current === undefined || current === null) {
return defaultValue;
}
current = current[key];
}
return current;
}
// Usage
console.log(lodashGet(obj, "user.phone[0].primary", "Debnath"));
console.log(lodashGet(obj, ["user", "address", "place"], "Debnath"));
Enhanced Implementation
Handling Empty Strings and Edge Cases
function lodashGet(object, path, defaultValue) {
if (object === null || object === undefined) {
return defaultValue;
}
// Handle empty path
if (!path || (Array.isArray(path) && path.length === 0)) {
return object;
}
// Normalize path
const keys = Array.isArray(path)
? path
: String(path)
.replace(/\[(\d+)\]/g, ".$1")
.split(".")
.filter(key => key !== "");
let current = object;
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
if (current === null || current === undefined) {
return defaultValue;
}
current = current[key];
}
return current === undefined ? defaultValue : current;
}
With Type Checking
function lodashGet(object, path, defaultValue) {
// Handle null/undefined object
if (object == null) {
return defaultValue;
}
// Handle invalid path
if (path == null) {
return object;
}
// Convert path to array
const keys = Array.isArray(path)
? path
: String(path)
.replace(/\[(\d+)\]/g, ".$1")
.replace(/\["([^"]+)"\]/g, ".$1")
.replace(/\['([^']+)'\]/g, ".$1")
.split(".")
.filter(Boolean);
if (keys.length === 0) {
return object;
}
let result = object;
for (const key of keys) {
if (result == null) {
return defaultValue;
}
result = result[key];
}
return result === undefined ? defaultValue : result;
}
Advanced Features
With Function Path
function lodashGet(object, path, defaultValue) {
if (typeof path === "function") {
return path(object) ?? defaultValue;
}
// ... rest of implementation
}
With Custom Separator
function lodashGet(object, path, defaultValue, separator = ".") {
if (object == null) {
return defaultValue;
}
const keys = Array.isArray(path)
? path
: String(path).split(separator).filter(Boolean);
let current = object;
for (const key of keys) {
if (current == null) {
return defaultValue;
}
current = current[key];
}
return current === undefined ? defaultValue : current;
}
Use Cases
1. Safe Property Access
// ❌ Without lodash get - can throw error
const city = user.address.city; // Error if address is undefined
// ✅ With lodash get - safe access
const city = lodashGet(user, "address.city", "Unknown");
2. API Response Handling
const response = await fetch("/api/user").then(r => r.json());
const email = lodashGet(response, "data.user.email", "no-email@example.com");
const phone = lodashGet(response, "data.user.phone[0].number", null);
3. Configuration Access
const config = {
app: {
api: {
baseUrl: "https://api.example.com",
timeout: 5000
}
}
};
const timeout = lodashGet(config, "app.api.timeout", 3000);
const baseUrl = lodashGet(config, "app.api.baseUrl", "https://default.com");
4. Form Data Access
const formData = {
personal: {
name: "John",
contacts: [
{ type: "email", value: "john@example.com" }
]
}
};
const email = lodashGet(formData, "personal.contacts[0].value", "");
Comparison with Optional Chaining
Optional Chaining (ES2020)
// Modern approach
const city = user?.address?.city ?? "Unknown";
const phone = user?.contacts?.[0]?.number ?? null;
Lodash get
// Works in older browsers
const city = lodashGet(user, "address.city", "Unknown");
const phone = lodashGet(user, "contacts[0].number", null);
Performance Optimization
Cached Path Parsing
const pathCache = new Map();
function parsePath(path) {
if (pathCache.has(path)) {
return pathCache.get(path);
}
const keys = Array.isArray(path)
? path
: String(path)
.replace(/\[(\d+)\]/g, ".$1")
.split(".")
.filter(Boolean);
pathCache.set(path, keys);
return keys;
}
function lodashGet(object, path, defaultValue) {
if (object == null) {
return defaultValue;
}
const keys = parsePath(path);
let current = object;
for (const key of keys) {
if (current == null) {
return defaultValue;
}
current = current[key];
}
return current === undefined ? defaultValue : current;
}
Related Functions
has() - Check if path exists
function lodashHas(object, path) {
return lodashGet(object, path) !== undefined;
}
set() - Set nested value
function lodashSet(object, path, value) {
const keys = Array.isArray(path)
? path
: String(path).split(".").filter(Boolean);
let current = object;
for (let i = 0; i < keys.length - 1; i++) {
const key = keys[i];
if (current[key] == null || typeof current[key] !== "object") {
current[key] = {};
}
current = current[key];
}
current[keys[keys.length - 1]] = value;
return object;
}
Best Practices
- Always Provide Default: Use meaningful default values
- Use Array Paths: For dynamic paths, use arrays
- Handle Null/Undefined: Check object before accessing
- Cache Paths: For frequently accessed paths
- Consider Optional Chaining: Use
?.in modern code - Type Safety: Validate return types when needed
Common Patterns
Pattern 1: Safe Array Access
const firstItem = lodashGet(array, "[0]", null);
const lastItem = lodashGet(array, `[${array.length - 1}]`, null);
Pattern 2: Multiple Fallbacks
const value = lodashGet(obj, "path1",
lodashGet(obj, "path2",
lodashGet(obj, "path3", "default")));
Pattern 3: Conditional Access
const value = condition
? lodashGet(obj, "path.if.true", defaultValue)
: lodashGet(obj, "path.if.false", defaultValue);
Real-World Example
class ConfigManager {
constructor(config) {
this.config = config;
}
get(path, defaultValue) {
return lodashGet(this.config, path, defaultValue);
}
getNested(paths) {
return paths.map(path => lodashGet(this.config, path));
}
has(path) {
return lodashGet(this.config, path) !== undefined;
}
}
// Usage
const configManager = new ConfigManager({
api: { baseUrl: "https://api.example.com" },
ui: { theme: "dark" }
});
const baseUrl = configManager.get("api.baseUrl", "https://default.com");
const theme = configManager.get("ui.theme", "light");