目录

🧮 JavaScript 运算符

运算符也称为操作符,对一个或多个值进行运算或者操作。

# 算术运算符

运算符 描述 例子 x 结果 y 结果
+ 加法 x=y+2 7 5
- 减法 x=y-2 3 5
* 乘法 x=y*2 10 5
/ 除法 x=y/2 2.5 5
% 取模 x=y%2 1 5
** 求幂 x=y**2 25 5
++ 自增 x=++y 6 6
x=y++ 5 6
-- 自减 x=--y 4 4
x=y-- 5 4
  • 特殊的二元运算:除了加法以外,对非 Number 类型的值进行运算时,都会先转换为 Number 然后在做运算。

    x = 6 - '2' // 4
    y = '6' / '2' // 3
    
    1
    2
  • 对于加法运算时,如果是两个字符串进行相加,则会做拼串操作,将两个字符连接为一个字符串。任何值和字符串做加法,都会先转换为字符串,然后再拼串。二元 + 是唯一一个以这种方式支持字符串的运算符。

    x = 5 + 5;
    y = "5" + 5; // '55'
    z = "hello" + 5; // 'hello5'
    
    // 特别地,
    a = 2 + 2 + '1' // '41'
    
    1
    2
    3
    4
    5
    6
  • 注意:自增 / 自减只能应用于变量。试一下,将其应用于数值(比如 5++ )则会报错。

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

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

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

    • 前置形式:对 counter 做自增运算,返回的是新的值 2 。因此 alert 显示的是 2
    let counter = 1;
    let a = ++counter; // (*)
    
    alert(a); // 2
    
    1
    2
    3
    4
    • 后置形式:它同样对 counter 做加法,但是返回的是 旧值(做加法之前的值)。因此 alert 显示的是 1
    let counter = 1;
    let a = counter++;
    
    alert(a); // 1
    
    1
    2
    3
    4
    • 但是如果自增 / 自减的值不会被使用,那么两者形式没有区别:
    let counter = 0;
    counter++;
    ++counter;
    alert( counter );
    
    1
    2
    3
    4
    • 对变量进行自增操作,并且 需要立刻使用自增后的值,那么我们需要使用前置形式: alert(++counter); // 1 ;想要将一个数加一,但是想使用其自增之前的值,那么需要使用后置形式: alert( counter++ ); // 0

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

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

    上述列子降低了代码的可读性,并不推荐。还是建议依照「一行一个行为」的原则。

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

# 一元运算符

表示运算时操作数只要一个:

  • + 正号,不会对数字值产生任何影响,但是可以 ** 将一个非数字转换为数字:** 它的效果和 Number(...) 相同,但是更加简短。

    let a = true;  
    a = +a;  // 1
    
    let b = ""
    b = +"" // 0
    
    1
    2
    3
    4
    5

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

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

    也可以从上面例子看出,一元运算符先于二元运算符作用于运算元

  • - 符号,对一个数字进行符号位取反:

    var a = true;  
    a = -a;  // -0
    
    1
    2

    对字符串运用会得到结果 NaN

# 运算符优先级

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

运算符优先级表 (opens new window)

# 逻辑运算符

逻辑运算符 (javascript.info) (opens new window)

逻辑运算符用于测定变量或值之间的逻辑

运算符 描述 例子
&& and 所有为真才为真 (x < 10 && y> 1) 为 true
|| or 有一个为真即为真 (x==5 || y==5) 为 false
! not !(x==y) 为 true
  • || 运算符的应用:大多数情况下,逻辑或 || 会被用在 if 语句中,用来测试是否有 任何 给定的条件为 true

    let hour = 9;
    
    if (hour < 10 || hour > 18) {
      alert( 'The office is closed.' );
    }
    
    1
    2
    3
    4
    5
  • 或运算寻找第一个真值:一个或运算 || 的链,将返回第一个真值,如果不存在真值,就返回该链的最后一个值。

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

      let firstName = "";
      let lastName = "";
      let nickName = "SuperCoder";
      
      alert( firstName || lastName || nickName || "Anonymous"); // SuperCoder
      
      1
      2
      3
      4
      5
    • 短路求值|| 对其参数进行处理,直到达到第一个真值,然后立即返回该值,而无需处理其他参数。如果操作数不仅仅是一个值,而是一个有副作用的表达式,例如变量赋值或函数调用,那么这一特性的重要性就变得显而易见了。

      true || alert("not printed"); // alert没有被运行
      false || alert("printed");
      
      1
      2
  • 与运算寻找第一个假值:与和或运算很像。区别就是与运算返回第一个假值,而或运算返回第一个真值。

    // 如果第一个操作数是真值,
    // 与运算返回第二个操作数:
    alert( 1 && 0 ); // 0
    alert( 1 && 5 ); // 5
    
    // 如果第一个操作数是假值,
    // 与运算将直接返回它。第二个操作数会被忽略
    alert( null && 5 ); // null
    alert( 0 && "no matter what" ); // 0
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    • 如果所有的值都是真值,最后一个值将会被返回:

      alert( 1 && 2 && 3 ); // 3,最后一个值
      
      1
  • 与运算 && 在或运算 || 之前进行:与运算 && 的优先级比或运算 || 要高。所以代码 a && b || c && d&& 表达式加了括号完全一样: (a && b) || (c && d)

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

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

# ?? 空值合并

a ?? b 的结果是:

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

如果第一个参数不是 null/undefined ,则 ?? 返回第一个参数。否则,返回第二个参数。

应用场景:

  • 提供默认值:如果 user 的值不为 null/undefined 则显示 user ,否则显示 匿名

    let user;
    alert(user ?? "匿名");
    
    1
    2
    let user = "John";
    alert(user ?? "匿名");
    
    1
    2
  • 选择出第一个非 null/undefined 的值。

    let firstName = null;
    let lastName = null;
    let nickName = "Supercoder";
    
    // 显示第一个已定义的值:
    alert(firstName ?? lastName ?? nickName ?? "匿名"); // Supercoder
    
    1
    2
    3
    4
    5
    6

??|| 比较:

  • 或运算符 || 可以以与 ?? 运算符相同的方式使用。( alert(firstName || lastName || nickName || "Anonymous"); 同理)
  • 但是,或 || 运算符先于 ?? 出现,它自 JavaScript 诞生就存在。空值合并运算符 ?? 是最近才被添加到 JavaScript 中的。
  • || 返回第一个 值。 ?? 返回第一个 已定义的 值。
    • || 无法区分 false0 、空字符串 ""null/undefined 。它们都一样 —— 假值(falsy values)。如果其中任何一个是 || 的第一个参数,那么我们将得到第二个参数作为结果。
  • 优先级: ?? 运算符的优先级与 || 相同。空值合并运算符在 =? 运算前计算,但在大多数其他运算(例如 +* )之后计算。
  • 不能将 ??||&& 一起使用,JavaSript 会触发语法错误。除非使用括号明确指定了优先级

# 赋值运算符

若 x=10 和 y=5:

运算符 例子 等同于 运算结果
= x=y x=5
+= x+=y x=x+y x=15
-= x-=y x=x-y x=5
*= x*=y x=x*y x=50
/= x/=y x=x/y x=2
%= x%=y x=x%y x=0
  • 链式赋值:

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

    最好写为可读性更强的:

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

# 关系运算符

值的比较 (javascript.info) (opens new window)

比较值之间的关系:

  • 如果关系成立则返回 true ,关系不成立则返回 false
  • 如果比较的两个值是非数值,会将其转换为 Number 然后再比较。
  • 如果比较的两个值都是字符串,此时会比较字符串的 Unicode 编码,而不会转换为 Number
运算符 描述 比较 返回值
== 等于 x==8 false
x==5 true
=== 绝对等于(值和类型均相等) x==="5" false
x===5 true
!=  不等于 x!=8 true
!==  不绝对等于(值和类型有一个不相等,或两个都不相等) x!=="5" true
x!==5 false
>  大于 x>8 false
<  小于 x<8 true
>=  大于或等于 x>=8 false
<=  小于或等于 x<=8 true

特殊的值

  • NaNUndefined :由于 undefined 衍生自 null ,所以 null == undefined 会返回 true 。 但是 null === undefined 会返回 false
  • NaN 和任何数值都不相等,自身 NaN == NaNfalse
  • 判断一个值是否 NaN ,使用 isNaN() 函数;

# 三元运算符

先对条件表达式求值判断,如果判断结果为 true ,则执行语句 1,并返回执行结果;如果判断结果为 false ,则执行语句 2,并返回执行结果;

条件表达式 ? 语句1 : 语句2;
1

# 逗号运算符

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

let a = (1 + 2, 3 + 4); // 只有 3 + 4 运行, 1 + 2 的结果被丢弃

alert( a );
1
2
3

逗号运算符的优先级:逗号运算符的优先级非常低,比 = 还要低,因此上面你的例子中圆括号非常重要。如果没有圆括号: a = 1 + 2, 3 + 4 会先执行 + ,将数值相加得到 a = 3, 7 ,然后赋值运算符 = 执行 a = 3 ,然后逗号之后的数值 7 不会再执行,它被忽略掉了。相当于 (a = 1 + 2), 3 + 4

📢 上次更新: 2022/09/02, 10:18:16