Null-safe property access (and conditional assignment) in ES6/2015
Solution 1:
Update (2022-01-13): Seems people are still finding this, here's the current story:
- Optional Chaining is in the specification now (ES2020) and supported by all modern browsers, more in the archived proposal: https://github.com/tc39/proposal-optional-chaining
- babel-preset-env: If you need to support older environments that don't have it, this is probably what you want https://babeljs.io/docs/en/babel-preset-env
- Babel v7 Plugin: https://babeljs.io/docs/en/babel-plugin-proposal-optional-chaining
Update (2017-08-01): If you want to use an official plugin, you can try the alpha build of Babel 7 with the new transform. Your mileage may vary
https://www.npmjs.com/package/babel-plugin-transform-optional-chaining
Original:
A feature that accomplishes that is currently in stage 1: Optional Chaining.
https://github.com/tc39/proposal-optional-chaining
If you want to use it today, there is a Babel plugin that accomplishes that.
https://github.com/davidyaha/ecmascript-optionals-proposal
Solution 2:
It's not as nice as the ?. operator, but to achieve a similar result you could do:
user && user.address && user.address.postcode
Since null
and undefined
are both falsy values (see this reference), the property after the &&
operator is only accessed if the precedent it not null or undefined.
Alternatively, you could write a function like this:
function _try(func, fallbackValue) {
try {
var value = func();
return (value === null || value === undefined) ? fallbackValue : value;
} catch (e) {
return fallbackValue;
}
}
Usage:
_try(() => user.address.postcode) // return postcode or undefined
Or, with a fallback value:
_try(() => user.address.postcode, "none") // return postcode or a custom string
Solution 3:
2020 Solution, ?.
and ??
You can now directly use ?.
(Optional Chaining) inline to safely test for existence. All modern browsers support it.
??
(Nullish Coalescing) can be used to set a default value if undefined or null.
aThing = possiblyNull ?? aThing
aThing = a?.b?.c ?? possiblyNullFallback ?? aThing
If a property exists, ?.
proceeds to the next check, or returns the valid value. Any failure will immediately short-circuit and return undefined
.
const example = {a: ["first", {b:3}, false]}
example?.a // ["first", {b:3}, false]
example?.b // undefined
example?.a?.[0] // "first"
example?.a?.[1]?.a // undefined
example?.a?.[1]?.b // 3
domElement?.parentElement?.children?.[3]?.nextElementSibling
null?.() // undefined
validFunction?.() // result
(() => {return 1})?.() // 1
To ensure a default defined value, you can use ??
. If you require the first truthy value, you can use ||
.
example?.c ?? "c" // "c"
example?.c || "c" // "c"
example?.a?.[2] ?? 2 // false
example?.a?.[2] || 2 // 2
If you do not check a case, the left-side property must exist. If not, it will throw an exception.
example?.First // undefined
example?.First.Second // Uncaught TypeError: Cannot read property 'Second' of undefined
?.
Browser Support - 92%, Nov 2021
??
Browser Support - 92%
Mozilla Documentation
--
Logical nullish assignment, 2020+ solution
New operators are currently being added to the browsers, ??=
, ||=
and &&=
. They don't do quite what you are looking for, but could lead to same result depending on the aim of your code.
NOTE: These are not common in public browser versions yet, but Babel should transpile well. Will update as availability changes.
??=
checks if left side is undefined or null, short-circuiting if already defined. If not, the left side is assigned the right-side value. ||=
and &&=
are similar, but based on the ||
and &&
operators.
Basic Examples
let a // undefined
let b = null
let c = false
a ??= true // true
b ??= true // true
c ??= true // false
Object/Array Examples
let x = ["foo"]
let y = { foo: "fizz" }
x[0] ??= "bar" // "foo"
x[1] ??= "bar" // "bar"
y.foo ??= "buzz" // "fizz"
y.bar ??= "buzz" // "buzz"
x // Array [ "foo", "bar" ]
y // Object { foo: "fizz", bar: "buzz" }
Browser Support Nov 2021 - 90%
Mozilla Documentation