admin管理员组文章数量:1126407
Related to Is there a "null coalescing" operator in JavaScript? - JavaScript now has a ??
operator which I see in use more frequently. Previously most JavaScript code used ||
.
let userAge = null
// These values will be the same.
let age1 = userAge || 21
let age2 = userAge ?? 21
In what circumstances will ??
and ||
behave differently?
Related to Is there a "null coalescing" operator in JavaScript? - JavaScript now has a ??
operator which I see in use more frequently. Previously most JavaScript code used ||
.
let userAge = null
// These values will be the same.
let age1 = userAge || 21
let age2 = userAge ?? 21
In what circumstances will ??
and ||
behave differently?
- 22 Overview and motivation – ASDFGerte Commented Apr 28, 2020 at 13:15
9 Answers
Reset to default 880The 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'
As a very short rule, you could look at it the opposite way:
||
(or)returns the first "truthy" value
(or the last value if no "truthy" value exists)??
(nullish coalescing)returns the first "defined" value
(or the last value if no "defined" value exists)
Example
x = false || true; // --> true (the first 'truthy' value - parameter 2)
x = false ?? true; // --> false (the first 'defined' value - parameter 1)
Base on MDN docs:
Contrary to the logical OR (||) operator, the left operand is returned if it is a falsy value which is not
null
orundefined
.
Conceptual Example:
When use
||
for a falsy value that is NOTundefined
ornull
:false || 'name'; // ==> the 'name' is returned
But when using
??
for above case:false ?? 'name'; // ==> the false is returned
Real Example:
Assume, we have a phone
variable that is not mandatory in our form and the empty string (''
) is valid for us and we wanna doSomething()
if the phone
variable is null
or undefined
, now guess what:
When use
||
for a falsy value that is NOTundefined
ornull
:const phone = ''; // assume it became empty string from some action phone || doSomething(); // ==> damn, the doSomething is run // but we want to run it if it's `undefined` or `null` the empty string is valid for us
But when using
??
for above case:const phone = ''; // same assumption like above phone ?? doSomething(); // ==> yeah, that's right // the empty string is valid for us and the doSomething is not run
Note: actually it is an example and in a real project you can have a better sense of this lovely operation usage.
Attention: for the undefined
or null
both of them act like each other.
As described in the MDN:
Contrary to the logical OR (
||
) operator, the left operand is returned if it is a falsy value which is notnull
orundefined
. In other words, if you use||
to provide some default value to another variablefoo
, you may encounter unexpected behaviors if you consider some falsy values as usable (eg.''
or0
). See below for more examples.
And also in the answer to the question you linked:
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! :)
When the ||
is being used as a boolean conditional that goes to false. For example:
let userAge = false
// These values will be the same.
let age1 = userAge || 21 // 21
let age2 = userAge ?? 21 // false
The logical OR will still give the next value for anything that doesn't evaluate to true
. So it gives the value 21
in this case. Where ??
only handles null
and undefined
.
function f(input) {
const val = input || 1;
return 41 + val;
}
function g(input) {
const val = input ?? 1;
return 41 + val;
}
console.log("using ||:", f(0));
console.log("using ??:", g(0));
The null(ish) coalescing operator only works with null
and undefined
. So, use the null(ish) coalescing operator when you don't want those values but you will otherwise accept other falsy values:
console.log(null ?? "nullish");
console.log(undefined ?? "nullish");
console.log("" ?? "nullish");
console.log(0 ?? "nullish");
console.log(false ?? "nullish");
The logical OR will skip over any falsy value and give you the other thing. The logical OR will skip over any falsy value and give you the other parameter. This does work and is by now idiomatic, however it is not always what you want:
console.log(null || "falsy");
console.log(undefined || "falsy");
console.log("" || "falsy");
console.log(0 || "falsy");
console.log(false || "falsy");
Here are few rules for how to determine which one you need. The simplest tests:
- do you only want to protect against
null
(andundefined
- it's usually the same thing)? Then use??
. If you aren't sure, it's probably a good idea to default to the nullish coalescing operator. - do you know you also don't want
0
or""
, for example? Then use||
.
The second one is where it actually gets trickly. How do you know you need to discard falsy values? Well, the very first snippet shows what happens if you do that: f(0)
will discard the zero and thus produce a different result. This is a somewhat common source of bugs. Since the construct a = b || c
is common to introduce a fallback value (in this case c
) it might accidentally fall back to it when you didn't mean to.
function updateAge(years) {
var yearsToAdd = years || 1;
return this.age + yearsToAdd
}
This works if you want to provide a fallback for calling updateAge()
(no argument) but fails if you call updateAge(0)
(no update). Similarly, you could have:
function sayMyName(greeting) {
var prefix = greeting || "Hello, my name is ";
return prefix + this.firstName;
}
Again, this works for sayMyName()
(no argument) but fails for sayMyName("")
(explicitly no greeting).
To generalise, if you are providing a fallback value that's different to the falsy value, then you might have a problem. However, if your fallback is the falsy value - num || 0
or str || ""
then it doesn't really matter.
It's rare (or should be) that you might expect a mixed type (number, or string, or object, etc) and provide a fallback to it: input || fallback
is valid but will reject empty strings and zeroes. It's usually going to be wrong unless you explicitly don't want any of those.
To put it simply, you should likely use the nullish coalescing operator ??
at all times. It will be less cognitive load to figure out whether it's a potential bug or not. There is also not much reason to avoid it. It's newer than the boolean OR, so it doesn't work on older environments, that's true, however nowadays you should likely be transpiling your code for those. If you cannot or prefer not to, then you don't have a choice and should use the boolean OR.
In short, when you care that let a variable assigned from a possible null
undefined
source, and you wish to provide a default value to the variable, use the nullish coalescing operator ??
.
If you want to avoid messing yourself around with the JavaScript definition of falsy truthy [1], then avoid using ||.
nullish coalescing operator ??
JavaScript definition of falsy
a real example in angular
/* parse the url pattern
/search?keyword=mykeyword&page=3
/search?keyword=mykeyword
*/
ngOnInit(): void {
const keyword = this.route.snapshot.queryParamMap.get('keyword') ?? 'default keyword';
const page = this.route.snapshot.queryParamMap.get('page') ?? '0';
this.queryResult$ = this.service.getQueryResult(keyword, +page);
this.keyword = keyword;
}
[1]:
Each programming language has its own definition of falsy truthy. The basic approach to tell whether a value is a truthy value is that if the explicit type conversion function bool(value)
results in true
, then the value is truthy.
For those might work across languages, PHP and C# also have ??
. See PHP, C#.
The nullish coalescing operator (??
) in JavaScript only considers null
or undefined
as "nullish" values. If the left-hand side is any other value, even falsy values like ""
(empty string), 0
, or false
, it will not use the right-hand side:
"" ?? "Hello" ==> // ""
In this example, ""
(empty string) is a falsy value, but it is not null
or undefined
, so the nullish coalescing operator will not replace it with "Hello"
. Therefore, the result is ""
.
On the other Hand, you can use the logical OR (||
) operator if you want to replace ""
with "Hello"
. It considers any falsy value (like ""
, 0
, false
) and replaces it:
"" || "Hello" ==> // "Hello"
This would return "Hello"
because ""
is falsy.
本文标签: javascriptWhen should I use(nullish coalescing) vs(logical OR)Stack Overflow
版权声明:本文标题:javascript - When should I use ?? (nullish coalescing) vs || (logical OR)? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736687005a1947720.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论