javascript 我应该什么时候使用??(无效合并)与||(逻辑或)?

lf5gs5x2  于 2023-05-05  发布在  Java
关注(0)|答案(8)|浏览(114)

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

在什么情况下??||会有不同的行为?

pdsfdshx

pdsfdshx1#

如果left是falsy,则OR运算符||使用右值,而如果left是nullundefined,则空合并运算符??使用右值。
这些运算符通常用于在缺少第一个运算符时提供默认值。

但是,如果左值可能包含""0false(因为这些是falsy values),OR运算符||可能会有问题

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"

在许多情况下,如果left是nullundefined,则可能只需要right值。这就是nullish合并运算符??的作用:

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运算符||(除非有很好的理由不这样做)。

jm2pwxwz

jm2pwxwz2#

总之

Nullish Coalescing Operator??区分:

  • nullish 值(nullundefined
    • 错误但已定义 * 值(false0''等)

||(逻辑OR)对这两种情况的处理是相同的。
我创建了一个简单的图形来说明JavaScript中 nullishfalsey 值的关系:

进一步说明:

let x, y

x = 0
y = x || 'default'            // y = 'default'
y = x ?? 'default'            // y = 0

如上所述,运算符??||之间的区别在于,一个检查 * null * 值,另一个检查 falsey 值。但是,在许多情况下,它们的行为相同。这是因为在JavaScript中,每个 nullish 值也是 falsey(但不是每个 falsey 值都是 nullish)。
使用我们上面学到的知识,我们可以为不同的行为创建一些示例:

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可以区分无值和假值,因此如果您需要检查是否没有String或空String,它可能是有益的。通常,您可能希望在大多数情况下使用??而不是||
最后,也是最不重要的,这里有两个示例,它们的行为相同:

let y

y = null || 'default'        // y = 'default'
y = null ?? 'default'        // y = 'default'

y = undefined || 'default'   // y = 'default'
y = undefined ?? 'default'   // y = 'default'
3ks5zfa0

3ks5zfa03#

作为一个非常简短的规则,你可以用相反的方式来看待它:

  • ||(或)returns the first "truthy" value(如果不存在“truthy”值,则为最后一个值)
  • ??(nullish coalescing)returns the first "defined" value(如果不存在“defined”值,则为最后一个值)

示例

x = false || true; // -->  true   (the first 'truthy' value - parameter 2)
x = false ?? true; // -->  false  (the first 'defined' value - parameter 1)
qltillow

qltillow4#

MDN中所述:
与逻辑OR(||)运算符相反,如果左操作数是一个非nullundefined的假值,则返回左操作数。换句话说,如果你使用||为另一个变量foo提供一些默认值,如果你认为一些错误的值是可用的,你可能会遇到意想不到的行为(例如:''0)。更多示例见下文。
the answer to the question you linked中:
无论第一个操作数的类型如何,如果将其强制转换为Boolean结果为false,则赋值将使用第二个操作数。注意以下所有情况:

alert(Boolean(null)); // false
alert(Boolean(undefined)); // false
alert(Boolean(0)); // false
alert(Boolean("")); // false
alert(Boolean("false")); // true -- gotcha! :)
ktecyv1j

ktecyv1j5#

基于MDN docs
the logical OR (||) operator相反,如果左操作数是不是nullundefined的falsy值,则返回左操作数。

概念示例:

  • 当使用||作为NOTundefinednullfalsy 值时:
false || 'name'; // ==> the 'name' is returned
  • 但是当使用??用于上述情况时:
false ?? 'name'; // ==> the false is returned
  • 真实的**:假设,我们有一个phone变量,在我们的表单中不是强制性的,空字符串('')对我们有效,如果phone变量是nullundefined,我们想要doSomething(),现在猜猜看:
  • 当使用||作为NOTundefinednullfalsy 值时:
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

注意:实际上这是一个示例,在真实的项目中你可以更好地了解这个可爱的操作用法。
注意事项:对于undefinednull,它们的作用彼此类似。

xxls0lw8

xxls0lw86#

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)合并运算符 only 适用于nullundefined。所以,当你不想要这些值,但你会接受其他的假值时,使用null(ish)合并运算符

console.log(null      ?? "nullish");
console.log(undefined ?? "nullish");
console.log(""        ?? "nullish");
console.log(0         ?? "nullish");
console.log(false     ?? "nullish");

逻辑OR将跳过任何假值,并给予你另一个东西。逻辑OR将跳过任何假值,并为您提供其他参数。Thisdoeswork,现在已经习惯了,但是它并不总是你想要的:

console.log(null      || "falsy");
console.log(undefined || "falsy");
console.log(""        || "falsy");
console.log(0         || "falsy");
console.log(false     || "falsy");

这里有一些规则,可以帮助你确定你需要哪一个。最简单的测试:

  • 你只想保护null(和undefined-通常是一样的)吗?然后使用??。如果您不确定,最好默认为null合并运算符。
  • 你知道你也不想要0""吗?然后使用||

第二个是它实际上变得棘手的地方。你怎么知道你需要丢弃falsy值?好吧,第一个片段显示了如果你这样做会发生什么:f(0)将丢弃零,从而产生不同的结果。这是bug的一个常见来源。由于结构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("")失败(显式没有问候语)。
概括地说,如果你提供了一个与falsy值 * 不同 * 的回退值,那么你可能会有问题。但是,如果你的后备 * 是 * falsy值-num || 0str || "",那么这并不重要。
很少(或者应该是)您可能会期望混合类型(数字,或字符串,或对象等)并提供一个回退:input || fallback有效,但会拒绝空字符串和零。这通常是错误的,除非你明确地不想要任何这些。
简单地说,您应该始终使用空合并运算符??。这将是更少的认知负荷,以找出它是否是一个潜在的错误或没有。也没有太多的理由去避免它。它比布尔OR更新,所以它不能在旧的环境中工作,这是真的,但是现在你应该为那些编译你的代码。如果你不能或者不想这么做,那么你没有选择,应该使用布尔OR。

l5tcr1uw

l5tcr1uw7#

||被用作布尔条件时,它将变为false。例如:

let userAge = false

// These values will be the same. 
let age1 = userAge || 21 // 21
let age2 = userAge ?? 21 // false

逻辑OR仍然会为任何不计算为true的值给予下一个值。所以在这种情况下,它给出了21的值。其中??仅处理nullundefined

cgvd09ve

cgvd09ve8#

简而言之,当你关心让一个变量从一个可能的nullundefined源赋值,并且你希望为变量提供一个默认值时,使用空合并运算符??
如果你不想在JavaScript定义falsytruthy [1]时把自己搞得一团糟,那么就避免使用||.
nullish coalescing operator ??
JavaScript definition of falsy
一真实的例子

/* 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的定义。判断一个值是否是truthy值的基本方法是,如果显式类型转换函数bool(value)的结果是true,则该值是 truthy
对于那些可能跨语言工作的,PHP和C#也有??。参见PHPC#

相关问题