一、逻辑运算符常用于布尔(逻辑)值之间;当操作数都是布尔值时,返回值也是布尔值。
二、&& 和 || 返回的是一个特定的操作数的值,所以当它用于非布尔值的时候,返回值就可能是非布尔值。
三、逻辑运算符

运算符 范例 描述 示例
逻辑与(&&) expr1 && expr2 (逻辑与)如果expr1能被转换为false,那么返回expr1;否则,返回expr2。 var a1 = true && true // true
var a2 = true && false // false
var a3 = false && true // false
var a8 = false && false // false
var a4 = false && (3 == 4) // false
var a5 = ‘Cat’ && ‘Dog’ // Dog
var a6 = flase && ‘Cat’ // false
var a7 = ‘Cat’ && false // false
逻辑或(||) expr1 || expr2 (逻辑或)如果expr1能被转换为true,那么返回expr1;否则,返回expr2 var o1 = true || true // true
var o2 = false || true // true
var o3 = true || false // true
var o4 = false || (3 == 4) // false
var o5 = ‘Cat’ || ‘Dog’ // Cat
var o6 = false || ‘Cat’ // Cat
var o7 = ‘Cat’ || false // Cat
逻辑非(!) !expr (逻辑非)如果操作数能够转换为true则返回false;否则返回true var n1 = !true // false
var n2 = !false // true
var n3 = !’Cat’ // false

1、&&用于布尔值时,当操作数都为true时返回true
2、|| 用于布尔值时,当任何一个操作数为true则返回true,是false则返回false
四、能被转换为false/ falsy的值有null, 0 , NaN, 空字符串(””)和undefined
五、与运算&&的优先级比或运算||要高
【示例1】a && b || c && d 跟 && 表达式加了括号完全一样:(a && b) || (c && d)
六、不要用 || 或 && 来取代if
一、有时候,有人会将与运算符&&作为“简化if”的一种方式。
【示例1】

  1. let x = 1;
  2. (x > 0) && alert( 'Greater than zero!' );

1、&&右边的代码只有运算抵达到那里才能被执行。也就是,当且仅当(x > 0)为真。
2、所以我们基本可以类似地得到:

  1. let x = 1;
  2. if (x > 0) alert( 'Greater than zero!' );

3、虽然使用&&写出的变体看起来更短,但if更明显,并且往往更具可读性。因此,我们建议根据每个语法结构的用途来使用:如果我们想要if,就使用if;如果我们想要逻辑与,就使用&&。

短路求值 (Short-circuit evaluation)

一、作为逻辑表达式进行求值是从左到右,它们是为可能的“短路”的出现而使用以下规则进行测试:
【示例1】

  1. false && anything // 被短路求值为false
  2. true || anything // 被短路求值为true

1、逻辑的规则,保证这些评估是总是正确的。
2、上述表达式中的anything部分不会被求值,所以这样做不会产生任何副作用。

运算符类型

|| (或)

一、一个或运算 || 的链,将返回第一个真值,如果不存在真值,就返回该链的最后一个值

或运算寻找第一个真值

一、例如,我们有变量firstName、lastName和nickName,都是可选的(即可以是 undefined,也可以是假值)。
1、我们用或运算||来选择有数据的那一个,并显示出来(如果没有设置,则用”Anonymous”):

let firstName = "";
let lastName = "";
let nickName = "SuperCoder";

alert( firstName || lastName || nickName || "Anonymous"); // SuperCoder
如果所有变量的值都为假,结果就是"Anonymous"。

2、如果所有变量的值都为假,结果就是”Anonymous”。

短路求值(Short-circuit evaluation)

一、|| 对其参数进行处理,直到达到第一个真值,然后立即返回该值,而无需处理其他参数
二、如果操作数不仅仅是一个值,而是一个有副作用的表达式,例如变量赋值或函数调用,那么这一特性的重要性就变得显而易见了。
【示例1】

true || alert("not printed"); // 或运算符 || 在遇到 true 时立即停止运算,所以 alert 没有运行。
false || alert("printed");

&& (与)

与运算寻找第一个假值

一、与运算返回第一个假值,如果没有假值就返回最后一个值
【示例1】

// 如果第一个操作数是真值,
// 与运算返回第二个操作数:
alert( 1 && 0 ); // 0
alert( 1 && 5 ); // 5

// 如果第一个操作数是假值,
// 与运算将直接返回它。第二个操作数会被忽略
alert( null && 5 ); // null
alert( 0 && "no matter what" ); // 0

【示例2】可以在一行代码上串联多个值。查看第一个假值是如何被返回的

alert( 1 && 2 && null && 3 ); // null

【示例3】如果所有的值都是真值,最后一个值将会被返回

alert( 1 && 2 && 3 ); // 3,最后一个值

| 【示例】jsx中的bug
1、错误写法```javascript

本次不可导入{title}数量 {taskInfo.notAllowedCount && ( 导出明细 )}

![image.png](https://cdn.nlark.com/yuque/0/2022/png/355497/1651886573652-863193c6-a884-4148-ab75-8692fe734d8f.png#clientId=u655250ee-1d0b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=141&id=u56f7a3b9&margin=%5Bobject%20Object%5D&name=image.png&originHeight=406&originWidth=866&originalType=binary&ratio=1&rotation=0&showTitle=false&size=38222&status=done&style=none&taskId=u00fbe0c2-ac5c-4920-9ca4-d5427981aa6&title=&width=300)<br />错误原因:taskInfo.notAllowedCount值为0,是假值。与运算符直接返回它。<br />2、正确写法```javascript
<div>
  本次不可导入{title}数量
  {taskInfo.notAllowedCount !== 0 && (
    <span className={styles.exportText}>导出明细</span>
)}
  </div>



image.png | | —- |

! (非)

一、感叹符号!表示布尔非运算符
二、语法

result = !value;

三、逻辑非运算符接受一个参数,并按如下运作:
1、将操作数转化为布尔类型:true/false。
2、返回相反的值。
【示例1】

alert( !true ); // false
alert( !0 ); // true

四、两个非运算!!有时候用来将某个值转化为布尔类型:

alert( !!"non-empty string" ); // true
alert( !!null ); // false

1、也就是,第一个非运算将该值转化为布尔类型并取反,第二个非运算再次取反。最后我们就得到了一个任意值到布尔值的转化。
2、一个内置的Boolean函数,可以完成同样的事 :
【示例1】

alert( Boolean("non-empty string") ); // true
alert( Boolean(null) ); // false

五、非运算符 ! 的优先级在所有逻辑运算符里面最高,所以它总是在 && 和 || 之前执行。

?? 空值合并运算符

一、我们将值既不是null也不是undefined的表达式称为“已定义的(defined)”。
二、空值合并运算符(nullish coalescing operator)的写法为两个问号??。
三、a ?? b的结果是:

  • 如果a是已定义的,则结果为a,
  • 如果a不是已定义的,则结果为b。

1、换句话说,如果第一个参数不是null/undefined,则??返回第一个参数。否则,返回第二个参数。
四、空值合并运算符并不是什么全新的东西。它只是一种获得两者中的第一个“已定义的”值的不错的语法。
【示例1】我们可以使用我们已知的运算符重写result = a ?? b,像这样:

result = (a !== null && a !== undefined) ? a : b;

四、空值合并运算符??提供了一种从列表中选择第一个“已定义的”值的简便方式。
五、通常??的使用场景是,为可能是未定义的变量提供一个默认值。
【示例1】如果user是未定义的,我们则显示Anonymous:

let user;

alert(user ?? "Anonymous"); // Anonymous
当然,如果user的值为除null/undefined外的任意值,那么我们看到的将是它:


let user = "John";

alert(user ?? "Anonymous"); // John

六、我们还可以使用??序列从一系列的值中选择出第一个非null/undefined的值。
【示例1】假设我们在变量firstName、lastName或nickName中存储着一个用户的数据。如果用户决定不输入值,则所有这些变量的值都可能是未定义的。
1、我们想使用这些变量之一显示用户名,如果这些变量的值都是未定义的,则显示 “Anonymous”。
2、让我们使用??运算符来实现这一需求:

let firstName = null;
let lastName = null;
let nickName = "Supercoder";

// 显示第一个已定义的值:
alert(firstName ?? lastName ?? nickName ?? "Anonymous"); // Supercoder

与 || 比较

一、或运算符||可以以与??运算符相同的方式使用。
【示例1】在上面的代码中,我们可以用||替换掉??,也可以获得相同的结果:

let firstName = null;
let lastName = null;
let nickName = "Supercoder";

// 显示第一个真值:
alert(firstName || lastName || nickName || "Anonymous"); // Supercoder

1、或||运算符自 JavaScript 诞生就存在,因此开发者长期将其用于这种目的。
二、另一方面,空值合并运算符??是最近才被添加到 JavaScript 中的,它的出现是因为人们对 || 不太满意。
三、它们之间重要的区别是:

  • || 返回第一个真值。
  • ?? 返回第一个已定义的值。

1、换句话说,|| 无法区分false、0、空字符串””和null/undefined。它们都一样 —— 假值(falsy values)。如果其中任何一个是||的第一个参数,那么我们将得到第二个参数作为结果。
四、在实际中,我们可能只想在变量的值为null/undefined时使用默认值。也就是说,当该值确实未知或未被设置时。
【示例1】考虑下面这种情况:

let height = 0;

alert(height || 100); // 100
alert(height ?? 100); // 0
  • height || 100首先会检查height是否为一个假值,发现它确实是。
    • 所以,结果为第二个参数,100。
  • height ?? 100首先会检查height是否为null/undefined,发现它不是。
    • 所以,结果为height的原始值,0。

1、如果高度0为有效值,则不应将其替换为默认值,所以 ?? 能够得出正确的结果。

优先级

一、??运算符的优先级相当低:在MDN table中为5。因此,??在=和?之前计算,但在大多数其他运算符(例如,+和*)之后计算。
二、如果我们需要在还有其他运算符的表达式中使用??进行取值,需要考虑加括号:
【示例1】

let height = null;
let width = null;

// 重要:使用括号
let area = (height ?? 100) * (width ?? 50);

alert(area); // 5000

1、否则,如果我们省略了括号,则由于*的优先级比??高,它会先执行,进而导致错误的结果。

// 没有括号
let area = height ?? 100 * width ?? 50;

// ……与下面这行代码的计算方式相同(应该不是我们所期望的):
let area = height ?? (100 * width) ?? 50;

?? 与 && 或 || 一起使用

一、出于安全原因,JavaScript 禁止将??运算符与&&和||运算符一起使用,除非使用括号明确指定了优先级。
【示例1】下面的代码会触发一个语法错误:

let x = 1 && 2 ?? 3; // Syntax error

1、这个限制无疑是值得商榷的,但它被添加到语言规范中是为了避免人们从||切换到??时的编程错误。
2、可以明确地使用括号来解决这个问题:

let x = (1 && 2) ?? 3; // 正常工作了

alert(x); // 2