Is there a "null coalescing" operator in JavaScript?
Solution 1
Update
JavaScript now supports the nullish coalescing operator (??). It returns its right-hand-side operand when its left-hand-side operand is null
or undefined
, and otherwise returns its left-hand-side operand.
Old Answer
Please check compatibility before using it.
The JavaScript equivalent of the C# null coalescing operator (??
) is using a logical OR (||
):
var whatIWant = someString || "Cookies!";
There are cases (clarified below) that the behaviour won't match that of C#, but this is the general, terse way of assigning default/alternative values in JavaScript.
Clarification
Regardless of the type of the first operand, if casting it to a Boolean results in false
, the assignment will use the second operand. Beware of all the cases below:
alert(Boolean(null)); // false
alert(Boolean(undefined)); // false
alert(Boolean(0)); // false
alert(Boolean("")); // false
alert(Boolean("false")); // true -- gotcha! :)
This means:
var whatIWant = null || new ShinyObject(); // is a new shiny object
var whatIWant = undefined || "well defined"; // is "well defined"
var whatIWant = 0 || 42; // is 42
var whatIWant = "" || "a million bucks"; // is "a million bucks"
var whatIWant = "false" || "no way"; // is "false"
Solution 2
function coalesce() {
var len = arguments.length;
for (var i=0; i<len; i++) {
if (arguments[i] !== null && arguments[i] !== undefined) {
return arguments[i];
}
}
return null;
}
var xyz = {};
xyz.val = coalesce(null, undefined, xyz.val, 5);
// xyz.val now contains 5
this solution works like the SQL coalesce function, it accepts any number of arguments, and returns null if none of them have a value. It behaves like the C# ?? operator in the sense that "", false, and 0 are considered NOT NULL and therefore count as actual values. If you come from a .net background, this will be the most natural feeling solution.
Solution 3
Yes, it is coming soon. See proposal here and implementation status here.
It looks like this:
x ?? y
Example
const response = {
settings: {
nullValue: null,
height: 400,
animationDuration: 0,
headerText: '',
showSplashScreen: false
}
};
const undefinedValue = response.settings?.undefinedValue ?? 'some other default'; // result: 'some other default'
const nullValue = response.settings?.nullValue ?? 'some other default'; // result: 'some other default'
const headerText = response.settings?.headerText ?? 'Hello, world!'; // result: ''
const animationDuration = response.settings?.animationDuration ?? 300; // result: 0
const showSplashScreen = response.settings?.showSplashScreen ?? true; // result: false
Solution 4
If ||
as a replacement of C#'s ??
isn't good enough in your case, because it swallows empty strings and zeros, you can always write your own function:
function $N(value, ifnull) {
if (value === null || value === undefined)
return ifnull;
return value;
}
var whatIWant = $N(someString, 'Cookies!');
Solution 5
Nobody has mentioned in here the potential for NaN
, which--to me--is also a null-ish value. So, I thought I'd add my two-cents.
For the given code:
var a,
b = null,
c = parseInt('Not a number'),
d = 0,
e = '',
f = 1
;
If you were to use the ||
operator, you get the first non-false value:
var result = a || b || c || d || e || f; // result === 1
If you use the new ??
(null coalescing) operator, you will get c
, which has the value: NaN
vas result = a ?? b ?? c ?? d ?? e ?? f; // result === NaN
Neither of these seem right to me. In my own little world of coalesce logic, which may differ from your world, I consider undefined, null, and NaN as all being "null-ish". So, I would expect to get back d
(zero) from the coalesce method.
If anyone's brain works like mine, and you want to exclude NaN
, then this custom coalesce
method (unlike the one posted here) will accomplish that:
function coalesce() {
var i, undefined, arg;
for( i=0; i < arguments.length; i++ ) {
arg = arguments[i];
if( arg !== null && arg !== undefined
&& (typeof arg !== 'number' || arg.toString() !== 'NaN') ) {
return arg;
}
}
return null;
}
For those who want the code as short as possible, and don't mind a little lack of clarity, you can also use this as suggested by @impinball. This takes advantage of the fact that NaN is never equal to NaN. You can read up more on that here: Why is NaN not equal to NaN?
function coalesce() {
var i, arg;
for( i=0; i < arguments.length; i++ ) {
arg = arguments[i];
if( arg != null && arg === arg ) { //arg === arg is false for NaN
return arg;
}
}
return null;
}
Daniel Schaffer
Updated on January 16, 2022Comments
-
Daniel Schaffer over 2 years
Is there a null coalescing operator in Javascript?
For example, in C#, I can do this:
String someString = null; var whatIWant = someString ?? "Cookies!";
The best approximation I can figure out for Javascript is using the conditional operator:
var someString = null; var whatIWant = someString ? someString : 'Cookies!';
Which is sorta icky IMHO. Can I do better?
-
Aprillion almost 6 yearsnote from 2018:
x ?? y
syntax is now in stage 1 proposal status - nullish coalescing -
Jonathan Sudiaman almost 5 yearsThere is now a Babel plugin which incorporates this exact syntax.
-
Daniel Schaffer almost 5 yearsNote from 2019: now is stage 3 status!
-
Daniel Schaffer over 4 yearsNote from later in 2019: Nullish coalescing is available in TypeScript 3.7!
-
Kir Kanos over 4 yearsNote from January 2020: Nullish coalescing operator is available natively in Firefox 72 but optional chaining operator is still not.
-
Mass Dot Net about 4 yearsThe nullish coalescing operator (
x ?? y
) and optional chaining operator (user.address?.street
) are now both Stage 4. Here's a good description about what that means: 2ality.com/2015/11/tc39-process.html#stage-4%3A-finished .
-
-
Ates Goral over 15 yearsActually, null is a value. It's a special value of type Object. A variable being set to null means it contains data, the data being a reference to the null object. A variable can be defined with value undefined in your code. This is not the same as the variable not being declared.
-
Daniel Schaffer over 15 yearsalert(null || '') still alerts an empty string, and I think I actually like that alert('' || 'blah') alerts blah rather than an empty string - good to know though! (+1)
-
Ates Goral over 15 yearsThe actual difference between a variable being declared or not: alert(window.test)/*undefined*/; alert("test" in window)/*false*/; window.test = undefined; alert(window.test)/*undefined*/; alert("test" in window)/*true*/; for (var p in window) {/*p can be "test"*/}
-
some over 15 yearsStrings like "false", "undefined", "null", "0", "empty", "deleted" are all true since they are non-empty strings.
-
Justin Johnson over 13 yearsOf note is that
||
returns the first "truey" value or the last "falsey" one (if none can evaluate to true) and that&&
works in the opposite way: returning the last truey value or the first falsey one. -
Bob over 10 yearsI think I might actually prefer defining a function that returns
false
if (strictly) null/undefined andtrue
otherwise - using that with a logical or; it could be more readable than many nested functions calls. e.g.$N(a) || $N(b) || $N(c) || d
is more readable than$N($N($N(a, b), c), d)
. -
Claudia almost 9 yearsBest practices - treat arguments as array-like, take advantage of NaN !== NaN (
typeof
+num.toString() === 'NaN'
is redundant), store current argument in variable instead ofarguments[i]
. -
serge over 8 yearshowever (a bit paradoxal) you can define a variable with the undefined value
var u = undefined;
-
Haravikk over 6 yearsApologies for such a late addition, but I just wanted to note for completeness that this solution does have the caveat that it has no short-circuit evaluation; if your arguments are function calls then they will all be evaluated regardless of whether their value is returned, which differs from the behaviour of the logical OR operator, so is worth noting.
-
ToolmakerSteve over 4 years@AtesGoral re null. While what you say is true, by convention, "null" represents "the absence of (useful) data". Hence it is considered to be "no data". And lets not forget that this is an answer to a question about "a null coalescing operator"; in this context, null is definitely treated as "no data" - regardless of how it is represented internally.
-
Gerard ONeill over 2 yearsThis is gigantic!
-
Gerard ONeill over 2 yearsBefore the release of the operator, this talk was necessary. But since your answer is just inferior to and much later in time than @faithful's answer, I'd argue you had too much talk.
-
Inigo over 2 years@JustinJohnson makes a good point. This answer compares all three:
??
vs||
vs&&
.