现代 JavaScript 教程 — 逻辑运算符

逻辑运算符

JavaScript 里有三个逻辑运算符:||(或),&&(与),!(非)。javascript

虽然他们被称为“逻辑”运算符,但这些运算符却能够被应用于任意类型的值,而不只仅是布尔值。他们的结果也一样能够是任意类型。html

让咱们来详细看一下。java

||(或)

两个竖线符号表示了“或”运算:react

result = a || b;
复制代码

在传统的编程中,逻辑或仅可以操做布尔值。若是参与运算的任意一个参数为 true,返回的结果就为 true,不然返回 false算法

在 JavaScript 中,逻辑运算符更加灵活强大。可是首先咱们看一下操做数是布尔值的时候发生了什么。编程

下面是四种可能的逻辑组合:微信

alert( true || true );   // true
alert( false || true );  // true
alert( true || false );  // true
alert( false || false ); // false
复制代码

正如咱们所见,除了两个操做数都是 false 的状况,结果都是 trueide

若是操做数不是布尔值,那么它将会被转化为布尔值来参与运算。函数

例如,数字 1 将会被做为 true,数字 0 则做为 false学习

if (1 || 0) { // 工做原理至关于 if( true || false )
  alert( 'truthy!' );
}
复制代码

大多数状况,逻辑或 || 会被用在 if 语句中,用来测试是否有 任何 给定的条件为 true

例如:

let hour = 9;

if (hour < 10 || hour > 18) {
  alert( 'The office is closed.' );
}
复制代码

咱们能够传入更多的条件:

let hour = 12;
let isWeekend = true;

if (hour < 10 || hour > 18 || isWeekend) {
  alert( 'The office is closed.' ); // 是周末
}
复制代码

或运算寻找第一个真值

上文提到的逻辑处理多少有些传统了。下面让咱们看看 JavaScript 的“附加”特性。

拓展的算法以下所示。

给定多个参与或运算的值:

result = value1 || value2 || value3;
复制代码

或运算符 || 作了以下的事情:

  • 从左到右依次计算操做数。
  • 处理每个操做数时,都将其转化为布尔值。若是结果是 true,就中止计算,返回这个操做数的初始值。
  • 若是全部的操做数都被计算过(也就是,转换结果都是 false),则返回最后一个操做数。

返回的值是操做数的初始形式,不会作布尔转换。

也就是,一个或 "||" 运算的链,将返回第一个真值,若是不存在真值,就返回该链的最后一个值。

例如:

alert( 1 || 0 ); // 1(1 是真值)
alert( true || 'no matter what' ); //(true 是真值)

alert( null || 1 ); // 1(1 是第一个真值)
alert( null || 0 || 1 ); // 1(第一个真值)
alert( undefined || null || 0 ); // 0(全部的转化结果都是 false,返回最后一个值)
复制代码

与“纯粹的、传统的、仅仅处理布尔值的或运算”相比,这个规则就引发了一些颇有趣的用法。

  1. 获取变量列表或者表达式的第一个真值。

    假设咱们有几个变量,它们可能包含某些数据或者是 null/undefined。咱们须要选出第一个包含数据的变量。

    咱们能够这样应用或运算 ||

    let currentUser = null;
    let defaultUser = "John";
    
    let name = currentUser || defaultUser || "unnamed";
    
    alert( name ); // 选出了 “John” — 第一个真值
    复制代码

    若是 currentUserdefaultUser 都是假值,那么结果就是 "unnamed"

  2. 短路取值。

    操做数不只仅能够是值,还能够是任意表达式。或运算会从左到右计算并测试每一个操做数。当找到第一个真值,计算就会中止,并返回这个值。这个过程就叫作“短路取值”,由于它尽量地减小从左到右计算的次数。

    当表达式做为第二个参数而且有必定的反作用(side effects),好比变量赋值的时候,短路取值的状况就清楚可见。

    若是咱们运行下面的例子,x 将不会被赋值:

    let x;
    
    true || (x = 1);
    
    alert(x); // undefined,由于 (x = 1) 没有被执行
    复制代码

    若是第一个参数是 false,或运算将会继续,并计算第二个参数,也就会运行赋值操做。

    let x;
    
    false || (x = 1);
    
    alert(x); // 1
    复制代码

    赋值操做只是一个很简单的状况。可能有反作用,若是计算没有到达,反作用就不会发生。

    正如咱们所见,这种用法是“if 语句的简短方式”。第一个操做数被转化为布尔值,若是是假,那么第二个参数就会被执行。

    大多数状况下,最好使用常规的 if 语句,这样代码可读性更高,可是有时候这种方式会很简洁。

&&(与)

两个 & 符号表示 && 与操做:

result = a && b;
复制代码

传统的编程中,当两个操做数都是真值,与操做返回 true,不然返回 false

alert( true && true );   // true
alert( false && true );  // false
alert( true && false );  // false
alert( false && false ); // false
复制代码

使用 if 语句的例子:

let hour = 12;
let minute = 30;

if (hour == 12 && minute == 30) {
  alert( 'Time is 12:30' );
}
复制代码

就像或运算同样,与运算的操做数能够是任意类型的值:

if (1 && 0) { // 做为 true && false 来执行
  alert( "won't work, because the result is falsy" );
}
复制代码

与操做寻找第一个假值

给出多个参加与运算的值:

result = value1 && value2 && value3;
复制代码

与运算 && 作了以下的事:

  • 从左到右依次计算操做数。
  • 将处理每个操做数时,都将其转化为布尔值。若是结果是 false,就中止计算,并返回这个操做数的初始值。
  • 若是全部的操做数都被计算过(也就是,转换结果都是 true),则返回最后一个操做数。

换句话说,与操做符返回第一个假值,若是没有假值就返回最后一个值。

上面的规则和或运算很像。区别就是与运算返回第一个假值而或操做返回第一个真值。

例如:

// 若是第一个操做符是真值,
// 与操做返回第二个操做数:
alert( 1 && 0 ); // 0
alert( 1 && 5 ); // 5

// 若是第一个操做符是假值,
// 与操做直接返回它。第二个操做数被忽略
alert( null && 5 ); // null
alert( 0 && "no matter what" ); // 0
复制代码

咱们也能够在一行代码上串联多个值。查看第一个假值是否被返回:

alert( 1 && 2 && null && 3 ); // null
复制代码

若是全部的值都是真值,最后一个值将会被返回:

alert( 1 && 2 && 3 ); // 3,最后一个值
复制代码

与运算 && 在或操做符 || 以前执行

与运算 && 的优先级比或运算 || 要高。

因此代码 a && b || c && d 彻底跟 && 表达式加了括号同样:(a && b) || (c && d)

就像或运算同样,与运算 && 有时候可以代替 if

例如:

let x = 1;

(x > 0) && alert( 'Greater than zero!' );
复制代码

&& 右边的代码只有运算抵达到那里才能被执行。也就是,当且仅当 (x > 0) 返回了真值。

因此咱们基本能够相似地获得:

let x = 1;

if (x > 0) {
  alert( 'Greater than zero!' );
}
复制代码

&& 的代码变体看上去更短。可是 if 的含义更明显,可读性也更高。

因此建议是根据目的选择代码的结构。须要条件判断就用 if,须要与运算就用 &&

!(非)

感叹符号 ! 表示布尔非运算。

语法至关简单:

result = !value;
复制代码

操做符接受一个参数,并按以下运做:

  1. 将操做数转化为布尔类型:true/false
  2. 返回相反的值。

例如:

alert( !true ); // false
alert( !0 ); // true
复制代码

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

alert( !!"non-empty string" ); // true
alert( !!null ); // false
复制代码

也就是,第一个非运算将该值转化为布尔类型并取反,第二个非运算再次取反。最后咱们就获得了一个任意值到布尔值的转化。

有更多详细的方法能够完成一样的事 —— 一个内置的 Boolean 函数:

alert( Boolean("non-empty string") ); // true
alert( Boolean(null) ); // false
复制代码

非运算符 ! 的优先级在全部逻辑运算符里面最高,因此它老是在 &&|| 前执行。

做业题

先本身作题目再看答案。

1. 或运算的结果是什么?

重要程度:⭐️⭐️⭐️⭐️⭐️

以下代码将会输出什么?

alert( null || 2 || undefined );
复制代码

2. 或运算和 alerts 的结果是什么?

重要程度:⭐️⭐️⭐

下面的代码将会输出什么?

alert( alert(1) || 2 || alert(3) );
复制代码

3. 与操做的结果是什么?

重要程度:⭐️⭐️⭐️⭐️⭐️

下面这段代码将会显示什么?

alert( 1 && null && 2 );
复制代码

4. 与运算链接的 alerts 的结果是什么?

重要程度:⭐️⭐️⭐

这段代码将会显示什么?

alert( alert(1) && alert(2) );
复制代码

5. 或运算、与运算、或运算串联的结果

重要程度:⭐️⭐️⭐️⭐️⭐️

结果将会是什么?

alert( null || 2 && 3 || 4 );
复制代码

6. 检查值是否位于范围区间内

重要程度:⭐️⭐️⭐

写一个“if”条件句来检查 age 是否位于 1490 的闭区间。

“闭区间”意味着,age 的值能够取 1490

7. 检测值是否位于范围以外

重要程度:⭐️⭐️⭐

写一个 if 条件句,检查 age 是否不位于 14 到 90 的闭区间。

建立两个表达式:第一个用非运算 !,第二个不用。

8. 一个关于 "if" 的问题

重要程度:⭐️⭐️⭐️⭐️⭐️

下面哪个 alert 将会被执行?

if(...) 语句内表达式的结果是什么?

if (-1 || 0) alert( 'first' );
if (-1 && 0) alert( 'second' );
if (null || -1 && 1) alert( 'third' );
复制代码

9. 登录验证

重要程度:⭐️⭐️⭐

实现使用 prompt 进行登录校验的代码。

若是访问者输入 "Admin",那么使用 prompt 引导获取密码,若是输入的用户名为空或者按下了 key:Esc 键 —— 显示 "Canceled",若是是其余字符串 —— 显示 "I don't know you"。

密码的校验规则以下:

  • 若是输入的是 "TheMaster",显示 "Welcome!",
  • 其余字符串 —— 显示 "Wrong password",
  • 空字符串或取消了输入,显示 "Canceled."。

流程图:

请使用嵌套的 if 块。注意代码总体的可读性。

提示:将空字符串输入,prompt 会获取到一个空字符串 ''。Prompt 运行过程当中,按下 key:ESC 键会获得 null

答案:

在微信公众号「技术漫谈」后台回复 1-2-11 获取本题答案。


现代 JavaScript 教程:开源的现代 JavaScript 从入门到进阶的优质教程。React 官方文档推荐,与 MDN 并列的 JavaScript 学习教程

在线免费阅读:zh.javascript.info


扫描下方二维码,关注微信公众号「技术漫谈」,订阅更多精彩内容。

相关文章
相关标签/搜索