The OR operator || uses the right value if left is falsy, while the nullish coalescing operator ?? uses the right value if left is null or undefined.
These operators are often used to provide a default value if the first one is missing.
But the OR operator || can be problematic if your left value might contain "" or 0 or false (because these are falsy values):
console.log(12 || "not found") // 12
console.log(0 || "not found") // "not found"
console.log("jane" || "not found") // "jane"
console.log("" || "not found") // "not found"
console.log(true || "not found") // true
console.log(false || "not found") // "not found"
console.log(undefined || "not found") // "not found"
console.log(null || "not found") // "not found"
In many cases, you might only want the right value if left is null or undefined. That's what the nullish coalescing operator ?? is for:
console.log(12 ?? "not found") // 12
console.log(0 ?? "not found") // 0
console.log("jane" ?? "not found") // "jane"
console.log("" ?? "not found") // ""
console.log(true ?? "not found") // true
console.log(false ?? "not found") // false
console.log(undefined ?? "not found") // "not found"
console.log(null ?? "not found") // "not found"
While the ?? operator isn't available in current LTS versions of Node (v10 and v12), you can use it with some versions of TypeScript or Node:
The ?? operator was added to TypeScript 3.7 back in November 2019.
And more recently, the ?? operator was included in ES2020, which is supported by Node 14 (released in April 2020).
When the nullish coalescing operator ?? is supported, I typically use it instead of the OR operator || (unless there's a good reason not to).
javascript - When should I use ?? (nullish coalescing) vs || (logical OR)? - Stack Overflow
What does the !! (double exclamation mark) operator do in JavaScript? - Stack Overflow
javascript - What is double question mark equal? - Stack Overflow
New Nullish Coalescing (?? Double question mark ) Operator in Typescript & Javascript
It's very recent, it was moved to stage 4 (Finished) 5 months ago https://github.com/tc39/proposal-nullish-coalescing
More on reddit.comVideos
The OR operator || uses the right value if left is falsy, while the nullish coalescing operator ?? uses the right value if left is null or undefined.
These operators are often used to provide a default value if the first one is missing.
But the OR operator || can be problematic if your left value might contain "" or 0 or false (because these are falsy values):
console.log(12 || "not found") // 12
console.log(0 || "not found") // "not found"
console.log("jane" || "not found") // "jane"
console.log("" || "not found") // "not found"
console.log(true || "not found") // true
console.log(false || "not found") // "not found"
console.log(undefined || "not found") // "not found"
console.log(null || "not found") // "not found"
In many cases, you might only want the right value if left is null or undefined. That's what the nullish coalescing operator ?? is for:
console.log(12 ?? "not found") // 12
console.log(0 ?? "not found") // 0
console.log("jane" ?? "not found") // "jane"
console.log("" ?? "not found") // ""
console.log(true ?? "not found") // true
console.log(false ?? "not found") // false
console.log(undefined ?? "not found") // "not found"
console.log(null ?? "not found") // "not found"
While the ?? operator isn't available in current LTS versions of Node (v10 and v12), you can use it with some versions of TypeScript or Node:
The ?? operator was added to TypeScript 3.7 back in November 2019.
And more recently, the ?? operator was included in ES2020, which is supported by Node 14 (released in April 2020).
When the nullish coalescing operator ?? is supported, I typically use it instead of the OR operator || (unless there's a good reason not to).
In short
The Nullish Coalescing Operator ?? distinguishes between:
- nullish values (
null,undefined) - falsey but defined values (
false,0,''etc.)
|| (logical OR) treats both of these the same.
I created a simple graphic to illustrate the relationship of nullish and falsey values in JavaScript:

Further explanation:
let x, y
x = 0
y = x || 'default' // y = 'default'
y = x ?? 'default' // y = 0
As seen above, the difference between the operators ?? and || is that one is checking for nullish values and one is checking for falsey values. However, there are many instances where they behave the same. That is because in JavaScript every nullish value is also falsey (but not every falsey value is nullish).
Using what we learned above we can create a few examples for different behavior:
let y
y = false || 'default' // y = 'default'
y = false ?? 'default' // y = false
y = 0n || 'default' // y = 'default'
y = 0n ?? 'default' // y = 0n
y = NaN || 'default' // y = 'default'
y = NaN ?? 'default' // y = NaN
y = '' || 'default' // y = 'default'
y = '' ?? 'default' // y = ''
Since the new Nullish Coalescing Operator can differentiate between no value and a falsey value, it can be beneficial if you, for example, need to check if there is no string or an empty string. Generally, you probably want to use ?? instead of || most of the time.
Last and also least here are the two instances where they behave the same:
let y
y = null || 'default' // y = 'default'
y = null ?? 'default' // y = 'default'
y = undefined || 'default' // y = 'default'
y = undefined ?? 'default' // y = 'default'
It converts Object to boolean. If it was falsy (e.g., 0, null, undefined, etc.), it would be false, otherwise, true.
!object // Inverted Boolean
!!object // Noninverted Boolean, so true Boolean representation
So !! is not an operator; it's just the ! operator twice.
It is generally simpler to do:
Boolean(object) // Boolean
Real World Example "Test IE version":
const isIE8 = !! navigator.userAgent.match(/MSIE 8.0/);
console.log(isIE8); // Returns true or false
If you ⇒
console.log(navigator.userAgent.match(/MSIE 8.0/));
// Returns either an Array or null
But if you ⇒
console.log(!!navigator.userAgent.match(/MSIE 8.0/));
// Returns either true or false
It's a horribly obscure way to do a type conversion.
! means NOT. So !true is false, and !false is true. !0 is true, and !1 is false.
So you're converting a value to a Boolean, inverting it, and then inverting it again.
// Maximum Obscurity:
val.enabled = !!userId;
// Partial Obscurity:
val.enabled = (userId != 0) ? true : false;
// And finally, much easier to understand:
val.enabled = (userId != 0);
// Or just
val.enabled = Boolean(userId);
Note: the middle two expressions aren't exactly equivalent to the first expression when it comes to some edge cases (when userId is [], for example) due to the way the != operator works and what values are considered truthy.