我应该什么时候使用?? (无效合并)与 || (逻辑或)?
When should I use ?? (nullish coalescing) vs || (logical OR)?
与 Is there a "null coalescing" operator in JavaScript? 相关 - JavaScript 现在有一个 ??
运算符,我发现它使用得更频繁。以前大多数 JavaScript 代码使用 ||
.
let userAge = null
// These values will be the same.
let age1 = userAge || 21
let age2 = userAge ?? 21
在什么情况下??
和||
会有不同的表现?
如MDN所述:
Contrary to the logical OR (||
) operator, the left operand is returned if it is a falsy value which is not null
or undefined
. In other words, if you use ||
to provide some default value to another variable foo
, you may encounter unexpected behaviors if you consider some falsy values as usable (eg. ''
or 0
). See below for more examples.
还有 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! :)
当 ||
被用作变为 false 的布尔条件时。例如:
let userAge = false
// These values will be the same.
let age1 = userAge || 21 // 21
let age2 = userAge ?? 21 // false
逻辑 OR 仍然会为计算结果不为 true
的任何值给出下一个值。所以在这种情况下它给出了值 21
。其中 ??
仅处理 null
和 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));
null(ish) 合并运算符 仅 适用于 null
和 undefined
。因此,当您不想要这些值时使用 null(ish) 合并运算符,否则您将接受其他虚假值:
console.log(null ?? "nullish");
console.log(undefined ?? "nullish");
console.log("" ?? "nullish");
console.log(0 ?? "nullish");
console.log(false ?? "nullish");
逻辑或将跳过任何虚假值并为您提供另一个值。
逻辑或将跳过任何虚假值并为您提供另一个参数。 This does work 现在是惯用的,但它并不总是你想要的:
console.log(null || "falsy");
console.log(undefined || "falsy");
console.log("" || "falsy");
console.log(0 || "falsy");
console.log(false || "falsy");
这里有一些关于如何确定您需要哪一个的规则。最简单的测试:
- 您是否只想防范
null
(和 undefined
- 通常是同一件事)?然后使用??
。如果您不确定,默认使用无效合并运算符可能是个好主意。
- 你知道你也不想要
0
或 ""
吗?然后使用 ||
。
第二个是它真正变得棘手的地方。您如何知道您需要丢弃虚假值?好吧,第一个片段显示了如果您这样做会发生什么:f(0)
将丢弃零,从而产生不同的结果。这是一个有点常见的错误来源。由于构造 a = b || c
通常会引入回退值(在本例中为 c
),它可能会在您无意时意外地回退到它。
function updateAge(years) {
var yearsToAdd = years || 1;
return this.age + yearsToAdd
}
如果您想为调用 updateAge()
(无参数)提供回退,则此方法有效,但如果您调用 updateAge(0)
(无更新),则会失败。同样,您可以:
function sayMyName(greeting) {
var prefix = greeting || "Hello, my name is ";
return prefix + this.firstName;
}
同样,这对 sayMyName()
(无参数)有效,但对 sayMyName("")
(明确无问候语)无效。
总而言之,如果您提供的回退值与虚假值不同,那么您可能会遇到问题。但是,如果您的后备 是 虚假值 - num || 0
或 str || ""
那么这并不重要。
您很少(或应该)期望混合类型(数字、字符串或对象等)并为其提供回退:input || fallback
有效但会拒绝空字符串和零。除非您明确不想要其中任何一个,否则通常会出错。
简而言之,您应该始终使用无效合并运算符 ??
。弄清楚它是否是潜在的错误将减少认知负担。也没有太多理由避免它。它比布尔值 OR 更新,因此它不适用于较旧的环境,这是真的,但是现在您可能应该为那些转换代码。如果您不能或不愿意,那么您别无选择,应该使用布尔值 OR。
OR 运算符 ||
在 left 为 falsy 时使用右值,而空值合并运算符 ??
在 left 为 null
或 [ 时使用右值=15=].
这些运算符通常用于在缺少第一个运算符时提供默认值。
但是如果您的左值可能包含 ""
或 0
或 false
(因为这些是 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"
在许多情况下,如果左边是 null
或 undefined
,您可能只需要右边的值。这就是无效合并运算符 ??
的用途:
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"
虽然 ??
运算符在 current LTS versions of Node(v10 和 v12)中不可用,但您可以将其与某些版本的 TypeScript 或 Node 一起使用:
??
运算符已于 2019 年 11 月添加到 TypeScript 3.7。
最近,??
运算符是 included in ES2020,它受 Node 14(2020 年 4 月发布)的支持。
当支持无效合并运算符 ??
时,我通常使用它来代替 OR 运算符 ||
(除非有充分的理由不这样做)。
基于MDN docs:
Contrary to the logical OR (||) operator, the left operand is returned if it is a falsy value which is not null
or undefined
.
概念示例:
当 ||
用于 falsy 值时 NOT undefined
或`空:
false || 'name'; // ==> the 'name' is returned
但在上述情况下使用 ??
时:
false ?? 'name'; // ==> the false is returned
实例:
假设,我们有一个 phone
变量,它在我们的表单中不是必需的,空字符串 (''
) 对我们有效,如果 phone
变量是null
或 undefined
,猜猜是什么:
当 ||
用于 falsy 值时 NOT undefined
或null
:
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
但在上述情况下使用 ??
时:
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
注意:其实是一个例子,在实际项目中你可以更好地体会这个可爱的操作用法。
注意:因为undefined
或null
两者的行为相似
简而言之:
Nullish Coalescing Operator区分nullish(null
,undefined
)和falsey但是定义 值(false
、0
、''
等)。有关详细信息,请参见下图。
对于 ||
(逻辑或)空值和假值相同。
let x, y
x = 0
y = x || 'default' // y = 'default'
y = x ?? 'default' // y = 0
如上所示,运算符 ??
和 ||
之间的区别在于,一个是检查 nullish 值,一个是检查 假 值。但是,在许多情况下它们的行为相同。这是因为在 JavaScript 中每个 nullish 值也是 falsey(但不是每个 falsey值为 nullish).
我创建了一个简单的图形来说明 nullish 和 falsey 值在 JavaScript:[=26= 中的关系]
利用我们在上面学到的知识,我们可以为不同的行为创建一些示例:
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 = ''
由于新的 Nullish Coalescing Operator 可以区分无值和假值,如果您需要检查是否没有字符串或空字符串,它会很有用。通常,大多数时候您可能希望使用 ??
而不是 ||
。
这里最后也是最不重要的是它们行为相同的两个实例:
let y
y = null || 'default' // y = 'default'
y = null ?? 'default' // y = 'default'
y = undefined || 'default' // y = 'default'
y = undefined ?? 'default' // y = 'default'
作为一个非常简短的规则,你可以从相反的角度看它:
||
(或)returns the first "truthy" value
(如果不存在“真实”值,则为最后一个值)
??
(无效合并)returns the first "defined" value
(如果不存在“已定义”值,则为最后一个值)
示例
x = false || true; // --> true (the first 'truthy' value - parameter 2)
x = false ?? true; // --> false (the first 'defined' value - parameter 1)
简而言之,当您关心从可能的 null
undefined
来源分配变量,并且您希望为变量提供 默认值时 , 使用无效合并运算符 ??
.
如果您想避免弄乱 JavaScript 伪真 [1] 的定义,请不要使用 ||。
nullish coalescing operator ??
JavaScript definition of falsy
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]:
每种编程语言都有自己对 falsy truthy 的定义。判断一个值是否为真值的基本方法是,如果显式类型转换函数 bool(value)
结果为 true
,则该值是 truthy.
对于那些可能跨语言工作的,PHP 和 C# 也有 ??
。参见 , C#。
与 Is there a "null coalescing" operator in JavaScript? 相关 - JavaScript 现在有一个 ??
运算符,我发现它使用得更频繁。以前大多数 JavaScript 代码使用 ||
.
let userAge = null
// These values will be the same.
let age1 = userAge || 21
let age2 = userAge ?? 21
在什么情况下??
和||
会有不同的表现?
如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.
还有 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! :)
当 ||
被用作变为 false 的布尔条件时。例如:
let userAge = false
// These values will be the same.
let age1 = userAge || 21 // 21
let age2 = userAge ?? 21 // false
逻辑 OR 仍然会为计算结果不为 true
的任何值给出下一个值。所以在这种情况下它给出了值 21
。其中 ??
仅处理 null
和 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));
null(ish) 合并运算符 仅 适用于 null
和 undefined
。因此,当您不想要这些值时使用 null(ish) 合并运算符,否则您将接受其他虚假值:
console.log(null ?? "nullish");
console.log(undefined ?? "nullish");
console.log("" ?? "nullish");
console.log(0 ?? "nullish");
console.log(false ?? "nullish");
逻辑或将跳过任何虚假值并为您提供另一个值。 逻辑或将跳过任何虚假值并为您提供另一个参数。 This does work 现在是惯用的,但它并不总是你想要的:
console.log(null || "falsy");
console.log(undefined || "falsy");
console.log("" || "falsy");
console.log(0 || "falsy");
console.log(false || "falsy");
这里有一些关于如何确定您需要哪一个的规则。最简单的测试:
- 您是否只想防范
null
(和undefined
- 通常是同一件事)?然后使用??
。如果您不确定,默认使用无效合并运算符可能是个好主意。 - 你知道你也不想要
0
或""
吗?然后使用||
。
第二个是它真正变得棘手的地方。您如何知道您需要丢弃虚假值?好吧,第一个片段显示了如果您这样做会发生什么:f(0)
将丢弃零,从而产生不同的结果。这是一个有点常见的错误来源。由于构造 a = b || c
通常会引入回退值(在本例中为 c
),它可能会在您无意时意外地回退到它。
function updateAge(years) {
var yearsToAdd = years || 1;
return this.age + yearsToAdd
}
如果您想为调用 updateAge()
(无参数)提供回退,则此方法有效,但如果您调用 updateAge(0)
(无更新),则会失败。同样,您可以:
function sayMyName(greeting) {
var prefix = greeting || "Hello, my name is ";
return prefix + this.firstName;
}
同样,这对 sayMyName()
(无参数)有效,但对 sayMyName("")
(明确无问候语)无效。
总而言之,如果您提供的回退值与虚假值不同,那么您可能会遇到问题。但是,如果您的后备 是 虚假值 - num || 0
或 str || ""
那么这并不重要。
您很少(或应该)期望混合类型(数字、字符串或对象等)并为其提供回退:input || fallback
有效但会拒绝空字符串和零。除非您明确不想要其中任何一个,否则通常会出错。
简而言之,您应该始终使用无效合并运算符 ??
。弄清楚它是否是潜在的错误将减少认知负担。也没有太多理由避免它。它比布尔值 OR 更新,因此它不适用于较旧的环境,这是真的,但是现在您可能应该为那些转换代码。如果您不能或不愿意,那么您别无选择,应该使用布尔值 OR。
OR 运算符 ||
在 left 为 falsy 时使用右值,而空值合并运算符 ??
在 left 为 null
或 [ 时使用右值=15=].
这些运算符通常用于在缺少第一个运算符时提供默认值。
但是如果您的左值可能包含 ""
或 0
或 false
(因为这些是 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"
在许多情况下,如果左边是 null
或 undefined
,您可能只需要右边的值。这就是无效合并运算符 ??
的用途:
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"
虽然 ??
运算符在 current LTS versions of Node(v10 和 v12)中不可用,但您可以将其与某些版本的 TypeScript 或 Node 一起使用:
??
运算符已于 2019 年 11 月添加到 TypeScript 3.7。
最近,??
运算符是 included in ES2020,它受 Node 14(2020 年 4 月发布)的支持。
当支持无效合并运算符 ??
时,我通常使用它来代替 OR 运算符 ||
(除非有充分的理由不这样做)。
基于MDN docs:
Contrary to the logical OR (||) operator, the left operand is returned if it is a falsy value which is not
null
orundefined
.
概念示例:
当
||
用于 falsy 值时 NOTundefined
或`空:false || 'name'; // ==> the 'name' is returned
但在上述情况下使用
??
时:false ?? 'name'; // ==> the false is returned
实例:
假设,我们有一个 phone
变量,它在我们的表单中不是必需的,空字符串 (''
) 对我们有效,如果 phone
变量是null
或 undefined
,猜猜是什么:
当
||
用于 falsy 值时 NOTundefined
或null
: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
但在上述情况下使用
??
时: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
注意:其实是一个例子,在实际项目中你可以更好地体会这个可爱的操作用法。
注意:因为undefined
或null
两者的行为相似
简而言之:
Nullish Coalescing Operator区分nullish(null
,undefined
)和falsey但是定义 值(false
、0
、''
等)。有关详细信息,请参见下图。
对于 ||
(逻辑或)空值和假值相同。
let x, y
x = 0
y = x || 'default' // y = 'default'
y = x ?? 'default' // y = 0
如上所示,运算符 ??
和 ||
之间的区别在于,一个是检查 nullish 值,一个是检查 假 值。但是,在许多情况下它们的行为相同。这是因为在 JavaScript 中每个 nullish 值也是 falsey(但不是每个 falsey值为 nullish).
我创建了一个简单的图形来说明 nullish 和 falsey 值在 JavaScript:[=26= 中的关系]
利用我们在上面学到的知识,我们可以为不同的行为创建一些示例:
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 = ''
由于新的 Nullish Coalescing Operator 可以区分无值和假值,如果您需要检查是否没有字符串或空字符串,它会很有用。通常,大多数时候您可能希望使用 ??
而不是 ||
。
这里最后也是最不重要的是它们行为相同的两个实例:
let y
y = null || 'default' // y = 'default'
y = null ?? 'default' // y = 'default'
y = undefined || 'default' // y = 'default'
y = undefined ?? 'default' // y = 'default'
作为一个非常简短的规则,你可以从相反的角度看它:
||
(或)returns the first "truthy" value
(如果不存在“真实”值,则为最后一个值)??
(无效合并)returns the first "defined" value
(如果不存在“已定义”值,则为最后一个值)
示例
x = false || true; // --> true (the first 'truthy' value - parameter 2)
x = false ?? true; // --> false (the first 'defined' value - parameter 1)
简而言之,当您关心从可能的 null
undefined
来源分配变量,并且您希望为变量提供 默认值时 , 使用无效合并运算符 ??
.
如果您想避免弄乱 JavaScript 伪真 [1] 的定义,请不要使用 ||。
nullish coalescing operator ??
JavaScript definition of falsy
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]:
每种编程语言都有自己对 falsy truthy 的定义。判断一个值是否为真值的基本方法是,如果显式类型转换函数 bool(value)
结果为 true
,则该值是 truthy.
对于那些可能跨语言工作的,PHP 和 C# 也有 ??
。参见