With the nullish coalescing operator (??
), one is tempted to use it for specifying defaults for non-existent object keys, as suggested in an answer here, e.g.:
let a = foo.bar ?? 'default';
However, it's alternatives in this case (mainly in
and hasOwnProperty
) have their caveats and risks. Calling <key> in <object>
matches keys in an object's prototype chain, as discussed here. Calling <object>.hasOwnProperty(<key>)
won't work, for example, if the object's hasOwnProperty
is shadowed, as discussed here. Surely, ??
has its own gotchas to watch out for.
What are the pitfalls with ??
compared to the other methods of checking for an existence of a key in any object?
In other words, are the risks of doing the following:
let a = foo.bar ?? 'default';
Closer to this
let a = 'bar' in foo ? foo.bar : 'default';
Or this
let a = foo.hasOwnProperty('bar') ? foo.bar : 'default';
Or this
let a = Object.prototype.hasOwnProperty.call(foo, 'bar') ? foo.bar : 'default';
Or are they different from either?
The risks you are talking about are irrelevant when you know what kind of object to expect, in your particular case one with a bar
property. There is no Object.prototype.bar
.
The "risks" of using ??
after a property access are exactly the same as the risks of doing the property access. Your statement let a = foo.bar ?? 'default';
is equivalent to
let a = foo.bar == null ? 'default' : foo.bar;
or (without accessing the property twice)
let a = foo.bar;
if (a == null) a = 'default';