Is there a null
-safe property access (null propagation / existence) operator in ES6 (ES2015/JavaScript.next/Harmony) like ?.
in
Going by the list here, there is currently no proposal to add safe traversal to Ecmascript. So not only is there no nice way to do this, but it is not going to be added in the forseeable future.
?.
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 - 82%, Oct 2020
?? Browser Support - 82%
Mozilla Documentation
--
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.
let a // undefined
let b = null
let c = false
a ??= true // true
b ??= true // true
c ??= true // false
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 Oct 2020 - 70%
Mozilla Documentation
Vanilla alternative for safe property access
(((a.b || {}).c || {}).d || {}).e
The most concise conditional assignment would probably be this
try { b = a.b.c.d.e } catch(e) {}
A safe deep get method seems like a natural fit for underscore.js but there the issue is avoiding string programming. Modifying @Felipe's answer to avoid string programming (or at least pushes edge cases back to the caller):
function safeGet(obj, props) {
return (props.length==1) ? obj[keys[0]] :safeGet(obj[props[0]], props.slice(1))
}
Example:
var test = {
a: {
b: 'b property value',
c: { }
}
}
safeGet(test, ['a', 'b'])
safeGet(test, "a.b".split('.'))
No. You may use lodash#get or something like that for this in JavaScript.
// Typescript
static nullsafe<T, R>(instance: T, func: (T) => R): R {
return func(instance)
}
// Javascript
function nullsafe(instance, func) {
return func(instance);
};
// use like this
const instance = getSomething();
let thing = nullsafe(instance, t => t.thing0.thing1.thingx);