• JavaScript 基础知识|基础运算符


    在这里插入图片描述

    🐧主页详情Choice~的个人主页
    📢作者简介:🏅物联网领域创作者🏅 and 🏅阿里专家博主🏅 and 🏅华为云享专家🏅
    ✍️人生格言:最慢的步伐不是跬步,而是徘徊;最快的脚步不是冲刺,而是坚持。
    🧑‍💻人生目标:成为一名合格的程序员,做未完成的梦:实现财富自由。
    🚩技术方向:NULL
    👻如果觉得博主的文章还不错的话,请三连支持一下博主哦
    💬给大家介绍一个我一直在用的求职刷题收割offe👉

    基础运算符,数学

    我们从学校里了解到过很多运算符,比如说加号 +、乘号 *、减号 - 等。

    在本章中,我们将从简单的运算符开始,然后着重介绍 JavaScript 特有的方面,这些是在学校中学习的数学所没有涵盖的。

    术语:“一元运算符”,“二元运算符”,“运算元”

    在正式开始前,我们先简单浏览一下常用术语。

    • 运算元 —— 运算符应用的对象。比如说乘法运算 5 * 2,有两个运算元:左运算元 5 和右运算元 2。有时候人们也称其为“参数”而不是“运算元”。

    • 如果一个运算符对应的只有一个运算元,那么它是 一元运算符。比如说一元负号运算符(unary negation)-,它的作用是对数字进行正负转换:

      let x = 1;
      
      x = -x;
      alert( x ); // -1,一元负号运算符生效
      
      • 1
      • 2
      • 3
      • 4
    • 如果一个运算符拥有两个运算元,那么它是 二元运算符。减号还存在二元运算符形式:

      let x = 1, y = 3;
      alert( y - x ); // 2,二元运算符减号做减运算
      
      • 1
      • 2

      严格地说,在上面的示例中,我们使用一个相同的符号表征了两个不同的运算符:负号运算符,即反转符号的一元运算符,减法运算符,是从另一个数减去一个数的二元运算符。

    数学

    支持以下数学运算:

    • 加法 +,
    • 减法 -,
    • 乘法 *,
    • 除法 /,
    • 取余 %,
    • 求幂 **.

    前四个都很简单,而 %** 则需要说一说。

    取余 %

    取余运算符是 %,尽管它看起来很像百分数,但实际并无关联。

    a % b 的结果是 a 整除 b 的 [余数](余数_百度百科 (baidu.com)))。

    例如:

    alert( 5 % 2 ); // 1,5 除以 2 的余数
    alert( 8 % 3 ); // 2,8 除以 3 的余数
    
    • 1
    • 2

    求幂 **

    求幂运算 a ** ba 提升至 ab 次幂。

    在数学中我们将其表示为 ab。

    例如:

    alert( 2 ** 2 ); // 2² = 4
    alert( 2 ** 3 ); // 2³ = 8
    alert( 2 ** 4 ); // 2⁴ = 16
    
    • 1
    • 2
    • 3

    就像在数学计算中一样,幂运算也适用于非整数。

    例如,平方根是指数为 ½ 的幂运算:

    alert( 4 ** (1/2) ); // 2(1/2 次方与平方根相同)
    alert( 8 ** (1/3) ); // 2(1/3 次方与立方根相同)
    
    • 1
    • 2

    用二元运算符 + 连接字符串

    我们来看一些学校算术未涉及的 JavaScript 运算符的特性。

    通常,加号 + 用于求和。

    但是如果加号 + 被应用于字符串,它将合并(连接)各个字符串:

    let s = "my" + "string";
    alert(s); // mystring
    
    • 1
    • 2

    注意:只要任意一个运算元是字符串,那么另一个运算元也将被转化为字符串。

    举个例子:

    alert( '1' + 2 ); // "12"
    alert( 2 + '1' ); // "21"
    
    • 1
    • 2

    你看,第一个运算元和第二个运算元,哪个是字符串并不重要。

    下面是一个更复杂的例子:

    alert(2 + 2 + '1' ); // "41",不是 "221"
    
    • 1

    在这里,运算符是按顺序工作。第一个 + 将两个数字相加,所以返回 4,然后下一个 + 将字符串 1 加入其中,所以就是 4 + '1' = '41'

    alert('1' + 2 + 2); // "122",不是 "14"
    
    • 1

    这里,第一个操作数是一个字符串,所以编译器将其他两个操作数也视为了字符串。2 被与 '1' 连接到了一起,也就是像 '1' + 2 = "12" 然后 "12" + 2 = "122" 这样。

    二元 + 是唯一一个以这种方式支持字符串的运算符。其他算术运算符只对数字起作用,并且总是将其运算元转换为数字。

    下面是减法和除法运算的示例:

    alert( 6 - '2' ); // 4,将 '2' 转换为数字
    alert( '6' / '2' ); // 3,将两个运算元都转换为数字
    
    • 1
    • 2

    数字转化,一元运算符 +

    加号 + 有两种形式。一种是上面我们刚刚讨论的二元运算符,还有一种是一元运算符。

    一元运算符加号,或者说,加号 + 应用于单个值,对数字没有任何作用。但是如果运算元不是数字,加号 + 则会将其转化为数字。

    例如:

    // 对数字无效
    let x = 1;
    alert( +x ); // 1
    
    let y = -2;
    alert( +y ); // -2
    
    // 转化非数字
    alert( +true ); // 1
    alert( +"" );   // 0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    它的效果和 Number(...) 相同,但是更加简短。

    我们经常会有将字符串转化为数字的需求。比如,如果我们正在从 HTML 表单中取值,通常得到的都是字符串。如果我们想对它们求和,该怎么办?

    二元运算符加号会把它们合并成字符串:

    let apples = "2";
    let oranges = "3";
    
    alert( apples + oranges ); // "23",二元运算符加号合并字符串
    
    • 1
    • 2
    • 3
    • 4

    如果我们想把它们当做数字对待,我们需要转化它们,然后再求和:

    let apples = "2";
    let oranges = "3";
    
    // 在二元运算符加号起作用之前,所有的值都被转化为了数字
    alert( +apples + +oranges ); // 5
    
    // 更长的写法
    // alert( Number(apples) + Number(oranges) ); // 5
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    从一个数学家的视角来看,大量的加号可能很奇怪。但是从一个程序员的视角,没什么好奇怪的:一元运算符加号首先起作用,它们将字符串转为数字,然后二元运算符加号对它们进行求和。

    为什么一元运算符先于二元运算符作用于运算元?接下去我们将讨论到,这是由于它们拥有 更高的优先级

    运算符优先级

    如果一个表达式拥有超过一个运算符,执行的顺序则由 优先级 决定。换句话说,所有的运算符中都隐含着优先级顺序。

    从小学开始,我们就知道在表达式 1 + 2 * 2 中,乘法先于加法计算。这就是一个优先级问题。乘法比加法拥有 更高的优先级

    圆括号拥有最高优先级,所以如果我们对现有的运算顺序不满意,我们可以使用圆括号来修改运算顺序,就像这样:(1 + 2) * 2

    在 JavaScript 中有众多运算符。每个运算符都有对应的优先级数字。数字越大,越先执行。如果优先级相同,则按照由左至右的顺序执行。

    这是一个摘抄自 Mozilla 的 优先级表(你没有必要把这全记住,但要记住一元运算符优先级高于二元运算符):

    优先级名称符号
    15一元加号+
    15一元负号-
    14求幂**
    13乘号*
    13除号/
    12加号+
    12减号-
    2赋值符=

    我们可以看到,“一元加号运算符”的优先级是 15,高于“二元加号运算符”的优先级 12。这也是为什么表达式 "+apples + +oranges" 中的一元加号先生效,然后才是二元加法。

    赋值运算符

    我们知道赋值符号 = 也是一个运算符。从优先级表中可以看到它的优先级非常低,只有 2

    这也是为什么,当我们赋值时,比如 x = 2 * 2 + 1,所有的计算先执行,然后 = 才执行,将计算结果存储到 x

    let x = 2 * 2 + 1;
    
    alert( x ); // 5
    
    • 1
    • 2
    • 3

    赋值 = 返回一个值

    = 是一个运算符,而不是一个有着“魔法”作用的语言结构。

    在 JavaScript 中,所有运算符都会返回一个值。这对于 +- 来说是显而易见的,但对于 = 来说也是如此。

    语句 x = value 将值 value 写入 x 然后返回 value

    下面是一个在复杂语句中使用赋值的例子:

    let a = 1;
    let b = 2;
    
    let c = 3 - (a = b + 1);
    
    alert( a ); // 3
    alert( c ); // 0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    上面这个例子,(a = b + 1) 的结果是赋给 a 的值(也就是 3)。然后该值被用于进一步的运算。

    有趣的代码,不是吗?我们应该了解它的工作原理,因为有时我们会在 JavaScript 库中看到它。

    不过,请不要写这样的代码。这样的技巧绝对不会使代码变得更清晰或可读。

    链式赋值(Chaining assignments)

    另一个有趣的特性是链式赋值:

    let a, b, c;
    
    a = b = c = 2 + 2;
    
    alert( a ); // 4
    alert( b ); // 4
    alert( c ); // 4
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    链式赋值从右到左进行计算。首先,对最右边的表达式 2 + 2 求值,然后将其赋给左边的变量:cba。最后,所有的变量共享一个值。

    同样,出于可读性,最好将这种代码分成几行:

    c = 2 + 2;
    b = c;
    a = c;
    
    • 1
    • 2
    • 3

    这样可读性更强,尤其是在快速浏览代码的时候。

    原地修改

    我们经常需要对一个变量做运算,并将新的结果存储在同一个变量中。

    例如:

    let n = 2;
    n = n + 5;
    n = n * 2;
    
    • 1
    • 2
    • 3

    可以使用运算符 +=*= 来缩写这种表示。

    let n = 2;
    n += 5; // 现在 n = 7(等同于 n = n + 5)
    n *= 2; // 现在 n = 14(等同于 n = n * 2)
    
    alert( n ); // 14
    
    • 1
    • 2
    • 3
    • 4
    • 5

    所有算术和位运算符都有简短的“修改并赋值”运算符:/=-= 等。

    这类运算符的优先级与普通赋值运算符的优先级相同,所以它们在大多数其他运算之后执行:

    let n = 2;
    
    n *= 3 + 5;
    
    alert( n ); // 16 (右边部分先被计算,等同于 n *= 8)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    自增/自减

    对一个数进行加一、减一是最常见的数学运算符之一。

    所以,对此有一些专门的运算符:

    • 自增 ++ 将变量与 1 相加:

      let counter = 2;
      counter++;      // 和 counter = counter + 1 效果一样,但是更简洁
      alert( counter ); // 3
      
      • 1
      • 2
      • 3
    • 自减 -- 将变量与 1 相减:

      let counter = 2;
      counter--;      // 和 counter = counter - 1 效果一样,但是更简洁
      alert( counter ); // 1
      
      • 1
      • 2
      • 3

    ⚠️重要:

    自增/自减只能应用于变量。试一下,将其应用于数值(比如 5++)则会报错。

    运算符 ++-- 可以置于变量前,也可以置于变量后。

    • 当运算符置于变量后,被称为“后置形式”:counter++
    • 当运算符置于变量前,被称为“前置形式”:++counter

    两者都做同一件事:将变量 counter1 相加。

    那么它们有区别吗?有,但只有当我们使用 ++/-- 的返回值时才能看到区别。

    详细点说。我们知道,所有的运算符都有返回值。自增/自减也不例外。前置形式返回一个新的值,但后置返回原来的值(做加法/减法之前的值)。

    为了直观看到区别,看下面的例子:

    let counter = 1;
    let a = ++counter; // (*)
    
    alert(a); // 2
    
    • 1
    • 2
    • 3
    • 4

    (*) 所在的行是前置形式 ++counter,对 counter 做自增运算,返回的是新的值 2。因此 alert 显示的是 2

    下面让我们看看后置形式:

    let counter = 1;
    let a = counter++; // (*) 将 ++counter 改为 counter++
    
    alert(a); // 1
    
    • 1
    • 2
    • 3
    • 4

    (*) 所在的行是后置形式 counter++,它同样对 counter 做加法,但是返回的是 旧值(做加法之前的值)。因此 alert 显示的是 1

    总结:

    • 如果自增/自减的值不会被使用,那么两者形式没有区别:

      let counter = 0;
      counter++;
      ++counter;
      alert( counter ); // 2,以上两行作用相同
      
      • 1
      • 2
      • 3
      • 4
    • 如果我们想要对变量进行自增操作,并且 需要立刻使用自增后的值,那么我们需要使用前置形式:

      let counter = 0;
      alert( ++counter ); // 1
      
      • 1
      • 2
    • 如果我们想要将一个数加一,但是我们想使用其自增之前的值,那么我们需要使用后置形式:

      let counter = 0;
      alert( counter++ ); // 0
      
      • 1
      • 2

    ℹ️自增/自减和其它运算符的对比

    ++/-- 运算符同样可以在表达式内部使用。它们的优先级比绝大部分的算数运算符要高。

    举个例子:

    let counter = 1;
    alert( 2 * ++counter ); // 4
    
    • 1
    • 2

    与下方例子对比:

    let counter = 1;
    alert( 2 * counter++ ); // 2,因为 counter++ 返回的是“旧值”
    
    • 1
    • 2

    尽管从技术层面上来说可行,但是这样的写法会降低代码的可阅读性。在一行上做多个操作 —— 这样并不好。

    当阅读代码时,快速的视觉“纵向”扫描会很容易漏掉 counter++,这样的自增操作并不明显。

    我们建议用“一行一个行为”的模式:

    let counter = 1;
    alert( 2 * counter );
    counter++;
    
    
    • 1
    • 2
    • 3
    • 4

    位运算符

    位运算符把运算元当做 32 位整数,并在它们的二进制表现形式上操作。

    这些运算符不是 JavaScript 特有的。大部分的编程语言都支持这些运算符。

    下面是位运算符:

    • 按位与 ( & )
    • 按位或 ( | )
    • 按位异或 ( ^ )
    • 按位非 ( ~ )
    • 左移 ( << )
    • 右移 ( >> )
    • 无符号右移 ( >>> )

    这些运算符很少被使用,一般是我们需要在最低级别(位)上操作数字时才使用。我们不会很快用到这些运算符,因为在 Web 开发中很少使用它们,但在某些特殊领域中,例如密码学,它们很有用。当你需要了解它们的时候,可以阅读 MDN 上的 【位操作符】章节。

    逗号运算符

    逗号运算符 , 是最少见最不常使用的运算符之一。有时候它会被用来写更简短的代码,因此为了能够理解代码,我们需要了解它。

    逗号运算符能让我们处理多个语句,使用 , 将它们分开。每个语句都运行了,但是只有最后的语句的结果会被返回。

    举个例子:

    let a = (1 + 2, 3 + 4);
    
    alert( a ); // 7(3 + 4 的结果)
    
    • 1
    • 2
    • 3

    这里,第一个语句 1 + 2 运行了,但是它的结果被丢弃了。随后计算 3 + 4,并且该计算结果被返回。

    ℹ️逗号运算符的优先级非常低

    请注意逗号运算符的优先级非常低,比 = 还要低,因此上面你的例子中圆括号非常重要。

    如果没有圆括号:a = 1 + 2, 3 + 4 会先执行 +,将数值相加得到 a = 3, 7,然后赋值运算符 = 执行 a = 3,然后逗号之后的数值 7 不会再执行,它被忽略掉了。相当于 (a = 1 + 2), 3 + 4

    为什么我们需要这样一个运算符,它只返回最后一个值呢?

    有时候,人们会使用它把几个行为放在一行上来进行复杂的运算。

    举个例子:

    // 一行上有三个运算符
    for (a = 1, b = 3, c = a * b; a < 10; a++) {
     ...
    }
    
    • 1
    • 2
    • 3
    • 4

    这样的技巧在许多 JavaScript 框架中都有使用,这也是为什么我们提到它。但是通常它并不能提升代码的可读性,使用它之前,我们要想清楚。

    ✅任务

    后置运算符和前置运算符

    重要程度: 5

    以下代码中变量 abcd 的最终值分别是多少?

    let a = 1, b = 1;
    
    let c = ++a; // ?
    let d = b++; // ?
    
    • 1
    • 2
    • 3
    • 4

    解决方案

    答案如下:

    • a = 2
    • b = 2
    • c = 2
    • d = 1
    let a = 1, b = 1;
    
    alert( ++a ); // 2,前置运算符返回最新值
    alert( b++ ); // 1,后置运算符返回旧值
    
    alert( a ); // 2,自增一次
    alert( b ); // 2,自增一次
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    赋值结果

    重要程度: 3

    下面这段代码运行完成后,代码中的 ax 的值是多少?

    let a = 2;
    
    let x = 1 + (a *= 2);
    
    • 1
    • 2
    • 3

    解决方案

    答案如下:

    • a = 4(乘以 2)
    • x = 5(相当于计算 1 + 4)

    类型转换

    重要程度: 5

    下面这些表达式的结果是什么?

    "" + 1 + 0
    "" - 1 + 0
    true + false
    6 / "3"
    "2" * "3"
    4 + 5 + "px"
    "$" + 4 + 5
    "4" - 2
    "4px" - 2
    "  -9  " + 5
    "  -9  " - 5
    null + 1
    undefined + 1
    " \t \n" - 2
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    好好思考一下,把它们写下来然后和答案比较一下。

    解决方案

    "" + 1 + 0 = "10" // (1)
    "" - 1 + 0 = -1 // (2)
    true + false = 1
    6 / "3" = 2
    "2" * "3" = 6
    4 + 5 + "px" = "9px"
    "$" + 4 + 5 = "$45"
    "4" - 2 = 2
    "4px" - 2 = NaN
    "  -9  " + 5 = "  -9  5" // (3)
    "  -9  " - 5 = -14 // (4)
    null + 1 = 1 // (5)
    undefined + 1 = NaN // (6)
    " \t \n" - 2 = -2 // (7)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    1. 有字符串的加法 "" + 1,首先会将数字 1 转换为一个字符串:"" + 1 = "1",然后我们得到 "1" + 0,再次应用同样的规则得到最终的结果。
    2. 减法 -(像大多数数学运算一样)只能用于数字,它会使空字符串 "" 转换为 0
    3. 带字符串的加法会将数字 5 加到字符串之后。
    4. 减法始终将字符串转换为数字,因此它会使 " -9 " 转换为数字 -9(忽略了字符串首尾的空格)。
    5. null 经过数字转换之后会变为 0
    6. undefined 经过数字转换之后会变为 NaN
    7. 字符串转换为数字时,会忽略字符串的首尾处的空格字符。在这里,整个字符串由空格字符组成,包括 \t\n 以及它们之间的“常规”空格。因此,类似于空字符串,所以会变为 0

    修正加法

    重要程度: 5

    这里有一段代码,要求用户输入两个数字并显示它们的总和。

    它的运行结果不正确。下面例子中的输出是 12(对于默认的 prompt 的值)。

    为什么会这样?修正它。结果应该是 3

    let a = prompt("First number?", 1);
    let b = prompt("Second number?", 2);
    
    alert(a + b); // 12
    
    • 1
    • 2
    • 3
    • 4

    解决方案

    原因是 prompt 以字符串的形式返回用户的输入。

    所以变量的值分别为 "1""2"

    let a = "1"; // prompt("First number?", 1);
    let b = "2"; // prompt("Second number?", 2);
    
    alert(a + b); // 12
    
    • 1
    • 2
    • 3
    • 4

    我们应该做的是,在 + 之前将字符串转换为数字。例如,使用 Number() 或在 prompt 前加 +

    例如,就在 prompt 之前加 +

    let a = +prompt("First number?", 1);
    let b = +prompt("Second number?", 2);
    
    alert(a + b); // 3
    
    • 1
    • 2
    • 3
    • 4

    或在 alert 中:

    let a = prompt("First number?", 1);
    let b = prompt("Second number?", 2);
    
    alert(+a + +b); // 3
    
    • 1
    • 2
    • 3
    • 4

    在最新的代码中,同时使用一元和二元的 +。看起来很有趣,不是吗?

  • 相关阅读:
    项目上线给后端,axios请求路径修改
    Matplotlib(六)quiver 箭头
    四、 端口
    Day03 Css的学习深入 background-X属性
    网心云容器魔方在iStoreOS下的多开
    美国服务器租用详细介绍与租用流程
    人均年薪70万!华为项目经理具备了哪些能力
    易基因|干货:m6A RNA甲基化MeRIP-seq测序分析实验全流程解析
    39、HumanNeRF
    数字档案管理系统单机版功能
  • 原文地址:https://blog.csdn.net/weixin_51568389/article/details/126252390