Safe Navigation With Lodash's get() Function
The _.get()
function in Lodash lets you
get deeply nested properties in an object without worrying about whether an
intermediate property is null
or undefined
. For example, suppose you have
the below object:
const landmark = {
name: 'Golden Gate Bridge',
// GeoJSON feature: https://geojson.org/
location: {
type: 'Feature',
properties: {
city: 'San Francisco',
state: 'California'
},
geometry: {
type: 'Point',
coordinates: [-122.4804438, 37.8199328]
}
}
};
To get the location.geometry.type
property, you could use landmark.location.geometry.type
. But if landmark.location
is undefined,
you would get the below error.
TypeError: Cannot read property 'geometry' of undefined
The _.get()
function lets you safely access the nested location.geometry.type
property, without having to explicity check whether landmark
, landmark.location
, or landmark.location.geometry
is undefined.
let type = _.get(landmark, 'location.geometry.type'); // 'Point'
delete landmark.location;
// `_.get()` doesn't error out, even though `landmark.location` is
// undefined.
type = _.get(landmark, 'location.geometry.type'); // undefined
// Even if `landmark` is `null`, `_.get()` does not error out.
type = _.get(null, 'location.geometry.type'); // undefined
Default Values
The third argument to _.get()
is the default value. If you pass a default value, _.get()
will return the default value where it would normally return undefined
.
landmark.location.geometry.type = undefined;
// If the value of the property is `undefined`, `_.get()` will return
// the default value.
let type = _.get(landmark, 'location.geometry.type', 'default'); // 'default'
delete landmark.location;
// If the property doesn't exist, `_.get()` will also return the default
// value.
type = _.get(landmark, 'location.geometry.type', 'default'); // 'default'
null
vs undefined
Be careful, the _.get()
function can return null
, even if you specify a default value.
landmark.location.geometry.type = null;
// If the value of the property is `null`, `_.get()` will **not** use
// the default value
let type = _.get(landmark, 'location.geometry.type', 'default'); // null
If you want to make sure _.get()
never resolves to a nullish value, you need
to explicitly check the return value using the conditional operator ?
.
landmark.location.geometry.type = null;
const checkDefault = (v, def) => v == null ? def : v;
// 'default'
let type = checkDefault(_.get(landmark, 'location.geometry.type'), 'default');