zoukankan      html  css  js  c++  java
  • JavaScript 基础知识 3

    #空值合并运算符 '??'
    既不是 null 也不是 undefined 的表达式称为“已定义的(defined)”。

    空值合并运算符(nullish coalescing operator)的写法为两个问号 ??。

    a ?? b 的结果是:

    如果 a 是已定义的,则结果为 a,
    如果 a 不是已定义的,则结果为 b。
    换句话说,如果第一个参数不是 null/undefined,则 ?? 返回第一个参数。否则,返回第二个参数。

    我们还可以使用 ?? 序列从一系列的值中选择出第一个非 null/undefined 的值。
    let firstName = null;
    let lastName = null;
    let nickName = "Supercoder";

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

    与 || 比较
    或运算符 || 可以以与 ?? 运算符相同的方式使用。
    空值合并运算符 ?? 是最近才被添加到 JavaScript 中的,它的出现是因为人们对 || 不太满意。
    它们之间重要的区别是:

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

    换句话说,|| 无法区分 false、0、空字符串 "" 和 null/undefined。它们都一样 —— 假值(falsy values)。如果其中任何一个是 || 的第一个参数,那么我们将得到第二个参数作为结果。

    例如,考虑下面这种情况:

    let height = 0;

    alert(height || 100); // 100
    alert(height ?? 100); // 0

    优先级
    ?? 运算符的优先级相当低:在 MDN table 中为 5。因此,?? 在 = 和 ? 之前计算,但在大多数其他运算符(例如,+ 和 *)之后计算。

    因此,如果我们需要在还有其他运算符的表达式中使用 ?? 进行取值,需要考虑加括号:

    let height = null;
    let width = null;

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

    alert(area); // 5000
    否则,如果我们省略了括号,则由于 * 的优先级比 ?? 高,它会先执行,进而导致错误的结果。

    ?? 与 && 或 || 一起使用
    出于安全原因,JavaScript 禁止将 ?? 运算符与 && 和 || 运算符一起使用,除非使用括号明确指定了优先级。

    下面的代码会触发一个语法错误:

    let x = 1 && 2 ?? 3; // Syntax error
    这个限制无疑是值得商榷的,但它被添加到语言规范中是为了避免人们从 || 切换到 ?? 时的编程错误。

    可以明确地使用括号来解决这个问题:

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

    alert(x); // 2

    总结
    空值合并运算符 ?? 提供了一种从列表中选择第一个“已定义的”值的简便方式。

    它被用于为变量分配默认值:

    // 当 height 的值为 null 或 undefined 时,将 height 的值设置为 100
    height = height ?? 100;
    ?? 运算符的优先级非常低,仅略高于 ? 和 =,因此在表达式中使用它时请考虑添加括号。

    如果没有明确添加括号,不能将其与 || 或 && 一起使用。


    #循环:while 和 for
    循环 是一种重复运行同一代码的方法。
    “while” 循环
    while 循环的语法如下:

    while (condition) {
    // 代码
    // 所谓的“循环体”
    }

    当 condition 为真时,执行循环体的 code。

    任何表达式或变量都可以是循环条件,而不仅仅是比较。在 while 中的循环条件会被计算,计算结果会被转化为布尔值。
    例如,while (i != 0) 可简写为 while (i):

    单行循环体不需要大括号
    如果循环体只有一条语句,则可以省略大括号 {…}:

    let i = 3;
    while (i) alert(i--);

    “do…while” 循环
    使用 do..while 语法可以将条件检查移至循环体 下面:

    do {
    // 循环体
    } while (condition);

    for” 循环
    for 循环更加复杂,但它是最常使用的循环形式。

    for 循环看起来就像这样:

    for (begin; condition; step) {
    // ……循环体……
    }
    我们通过示例来了解一下这三个部分的含义。下述循环从 i 等于 0 到 3(但不包括 3)运行 alert(i):

    for (let i = 0; i < 3; i++) { // 结果为 0、1、2
    alert(i);
    }

    跳出循环 break
    通常条件为假时,循环会终止。
    但我们随时都可以使用 break 指令强制退出。
    例如,下面这个循环要求用户输入一系列数字,在输入的内容不是数字时“终止”循环。

    let sum = 0;
    while (true) {
    let value = +prompt("Enter a number", '');
    if (!value) break; // (*)
    sum += value;
    }
    alert( 'Sum: ' + sum );

    如果用户输入空行或取消输入,在 (*) 行的 break 指令会被激活。它立刻终止循环,将控制权传递给循环后的第一行,即,alert。

        继续下一次迭代 continue
    continue 指令是 break 的“轻量版”。它不会停掉整个循环。而是停止当前这一次迭代,并强制启动新一轮循环(如果条件允许的话)。

    如果我们完成了当前的迭代,并且希望继续执行下一次迭代,我们就可以使用它。
    下面这个循环使用 continue 来只输出奇数:

    for (let i = 0; i < 10; i++) {
    //如果为真,跳过循环体的剩余部分。
    if (i % 2 == 0) continue;
    alert(i); // 1,然后 3,5,7,9
    }
    对于偶数的 i 值,continue 指令会停止本次循环的继续执行,将控制权传递给下一次 for 循环的迭代(使用下一个数字)。因此 alert 仅被奇数值调用。

    触发continue后,continue后的代码不会再执行,而是启动下一次for循环。


        break/continue 标签
    有时候我们需要从一次从多层嵌套的循环中跳出来。
    例如,下述代码中我们的循环使用了 i 和 j,从 (0,0) 到 (3,3) 提示坐标 (i, j):

    for (let i = 0; i < 3; i++) {
    for (let j = 0; j < 3; j++) {
    let input = prompt(`Value at coords (${i},${j})`, '');
    // 如果我想从这里退出并直接执行 alert('Done!')
    }
    }

    alert('Done!');

    我们需要提供一种方法,以在用户取消输入时来停止这个过程。
    在 input 之后的普通 break 只会打破内部循环。这还不够 —— 标签可以实现这一功能!
    标签 是在循环之前带有冒号的标识符:
    labelName: for (...) {
    ...
    }
    break <labelName> 语句跳出循环至标签处:
    outer: for (let i = 0; i < 3; i++) {
    for (let j = 0; j < 3; j++) {
    let input = prompt(`Value at coords (${i},${j})`, '');
    // 如果是空字符串或被取消,则中断并跳出这两个循环。
    if (!input) break outer; // (*)
    // 用得到的值做些事……
    }
    }
    alert('Done!');
    上述代码中,break outer 向上寻找名为 outer 的标签并跳出当前循环。
    因此,控制权直接从 (*) 转至 alert('Done!')。

    我们还可以将标签移至单独一行:

    outer:
    for (let i = 0; i < 3; i++) { ... }
    continue 指令也可以与标签一起使用。在这种情况下,执行跳转到标记循环的下一次迭代。

     

  • 相关阅读:
    LeetCode 到底怎么刷?GitHub 上多位大厂程序员亲测的高效刷题方式
    第 15 篇:接口的单元测试
    【译】GitHub 为什么挂?官方的可行性报告为你解答
    微服务常用的几种部署方式——蓝绿部署,滚动升级,灰度发布/金丝雀发布
    .net生成PDF文件的几种方式
    读取私有字体信息并进行相关判断
    Windows Locale Codes
    总结C#获取当前路径的7种方法
    Devexpress aspxgridview oncustomcallback 无刷新更新数据
    ArcGIS Pro 版本、版本号、发布年代
  • 原文地址:https://www.cnblogs.com/perfectdata/p/15391451.html
Copyright © 2011-2022 走看看