全网最全JavaScript运算符指南

本文将逐一讨论JavaScript中的运算符。并演示它们的功能和用法,帮助大家能够理解运算符在构建复杂表达式中的作用。

JavaScript运算符是什么?

花点时间查看以下代码片段:

jsx 复制代码
const x = 10, y = 20, z = 30;
console.log((x > y ? x : y) > z ? (x > y ? x : y) : z); // 令人疑惑吗?

如果你不能很快知道答案,请仔细阅读本文,再回来看这道题。

术语简介

在我们深入研究之前,介绍一些运算符常用的术语:

  • **操作数:**是运算符操作的项目。如果我们将运算符视为一种操作,那么操作数就是该操作应用于的对象。例如,在表达式5 + 3中,+是运算符(加法操作),而5和3是操作数,即要相加的数字。在JavaScript中,操作数可以是不同类型的,如数字、字符串、变量,甚至更复杂的表达式。
  • **强制类型转换:**是将一个值从一种原始类型转换为另一种原始类型的过程。例如,JavaScript可能会将数字更改为字符串,或者将非布尔值更改为布尔值。JavaScript中的原始类型包括StringNumberBigIntBooleanundefinedSymbolnull
  • NaN:代表不是数字 。它是Number类型的特殊值,表示无效或无法表示的数值。
  • 真值:是在布尔上下文中评估为true的值,而假值 在布尔上下文中评估为false,假值包括false00''nullundefinedNaNBigInt(0)

算术运算符

算术运算符 允许我们对值执行算术运算,并对数据进行转换。JavaScript中常用的算术运算符包括加法(+)、减法(-)、乘法(*)和除法(/)。除此之外,还有取模运算符(%),它返回除法操作的余数,以及增量(++)和减量(--)运算符,它们可以将值增加或减少1。

加法:+

加法运算符 执行两种不同的操作:数字相加和字符串连接。在使用+运算符计算表达式时,JavaScript首先将两个操作数转换为原始值。完成此操作后,它会检查两个操作数的类型。

如果一个操作数是字符串,则将另一个操作数也转换为字符串,然后连接这两个字符串。例如:

jsx 复制代码
'Hello, ' + 'World!' // Hello, World!
'The number is ' + 42 // 'The number is 42'

如果两个操作数都是BigInts,则执行BigInt加法。BigInt是一种特殊的数值类型,可以处理标准Number类型无法处理的大数值。

但如果一个操作数是BigInts,另一个不是,JavaScript会抛出TypeError

jsx 复制代码
const num1 = BigInt(12345678901234567890);
const num2 = BigInt(12345678901234567890);
num1 + num2 // 24691357802469134336n
num1 + 1 // Uncaught TypeError: Cannot mix BigInt and other types, use explicit conversions

对于所有其他情况,两个操作数都将转换为数字,并执行数字相加。例如:

jsx 复制代码
10 + 20 // 30
10 + true // 11 --- true会转换为值1

请注意,JavaScript有一些奇怪的输出:

jsx 复制代码
1 + { a: 1 } // '1[object Object]'

在这种情况下,JavaScript试图将对象{ a: 1 }转换为原始值,但最好它能做的就是将其转换为字符串[object Object],然后与数字1连接起来。

减法:``

JavaScript中的减法运算符 在使用上很简单:用一个数字减去另一个数字。与加法运算符一样,它也适用于BigInt类型。

如果两个操作数是数字或可以转换为数字,JavaScript执行数字减法:

jsx 复制代码
10 - 3 // 7
'100' - 30 // 70

如果两个操作数都是BigInts,JavaScript执行BigInt减法:

jsx 复制代码
const num1 = BigInt('9007199254740993');
const num2 = BigInt('3');
num1 - num2 // 900719925474

0990n

与加法运算符一样,当与非数字一起使用时,减法也可能产生意想不到的结果。例如,如果我们尝试减去无法转换为数字的内容,JavaScript将返回NaN,表示"不是数字":

jsx 复制代码
10 - 'Jim' // NaN

乘法:

乘法运算符适用于数字和BigInts

通常我们将对数字进行乘法运算:

jsx 复制代码
10 * 5 // 50

如果两个操作数都是BigInts,则执行BigInt乘法:

jsx 复制代码
const num1 = 9007199254740993n;
num1 * 2n // 18014398509481986n

与其他运算符一样,JavaScript尝试将非数字值转换为数字。如果无法这样做,它将返回NaN

jsx 复制代码
'100' * 30 // 3000
10 * 'Jim' // NaN

除法:/

除法运算符/)与数字和BigInts一起使用,方式与+-*类似。它首先将两个操作数转换为数字。

标准数值除法:

jsx 复制代码
10 / 2 // 5
10 / '2' // 5

处理BigInts时,除法运算符的行为稍有不同。它执行除法并丢弃任何余数,从效果上来说是向零截断结果:

jsx 复制代码
const num = 10n;
num / 3n // 3n,而不是3.333...n

除以零的结果将产生Infinity,除非是BigInt,在这种情况下会引发RangeError

如果我们尝试将数字除以无法转换为数字的值,JavaScript通常会返回NaN

模数(余数):%

模数运算符 用于找到一个数除以另一个数(称为被除数除数 )后的余数。这个算术运算符适用于数字和BigInts

当我们使用%运算符时,JavaScript首先将操作数转换为数字:

jsx 复制代码
10 % 3 // 1
'10' % 3 // 1

这是因为三除以十等于三(得到九),余下来的(余数)是一。

这个运算符的一个常见用例是检查一个数是奇数还是偶数:

jsx 复制代码
const isEven = num => num % 2 === 0;
isEven(1) // false
isEven(2) // true

这里使用了一个箭头函数和稍后会介绍的三重等号运算符。

模数运算符有一些特殊情况。例如,如果操作数中的一个是NaN,如果被除数是Infinity,或者如果除数是0,则操作返回NaN

另一方面,如果除数是Infinity,或者被除数是0,则操作返回被除数。

增量:++

增量运算符用于将变量的值增加1。它可以应用于NumberBigInt类型的操作数,根据它是后缀形式还是前缀形式,其行为会有所不同。

后缀增量

如果运算符放在操作数后面(num++),则增量操作在返回值之后执行。在这种情况下,变量的原始值在当前表达式中使用,然后在之后递增变量的值:

jsx 复制代码
let num = 5;
const result = num++;
console.log(result); // 5
console.log(num); // 6

前缀增量

如果运算符放在操作数前面(++num),则增量操作在返回值之前执行。在这种情况下,首先递增变量的值,然后在当前表达式中使用更新后的值:

jsx 复制代码
let num = 5;
const result = ++num;
console.log(result); // 6
console.log(num); // 6

减量:``

减量运算符 用于将变量的值减少1。与增量运算符类似,它可以应用于NumberBigInt类型的操作数,根据它是后缀形式还是前缀形式,其行为会有所不同。

后缀减量

当运算符放在操作数后面(num--)时,减量操作在返回值之后执行。在这种情况下,变量的原始值在当前表达式中使用,然后在之后递减变量的值:

jsx 复制代码
let num = 5;
const result = num--;
console.log(result); // 5
console.log(num); // 4

前缀减量

当运算符放在操作数前面(--num)时,减量操作在返回值之前执行。在这种情况下,首先递减变量的值,然后在当前表达式中使用更新后的值:

jsx 复制代码
let num = 5;
const result = --num;
console.log(result); // 4
console.log(num); // 4

与增量运算符一样,减量运算符只能用于可以更改的变量:

jsx 复制代码
const num = 5;
const result = num--; // Uncaught TypeError: Assignment to constant variable.

其他算术运算符

除了增量和减量运算符,JavaScript中还有其他一些算术运算符。

一元否定运算符-)用于否定数值,将其符号更改为相反的。例如,-5将是数字5的否定。

一元加运算符+)可用于显式将值转换为数字,当处理数字的字符串表示时很有用。例如,+'10'将字符串'10'转换为数字10

jsx 复制代码
const num = '10';
const res = +num; // 一元运算符将String转换为Number
res // 10

指数运算符**)用于将一个数值提升到某个幂次方。例如,2 ** 3表示2的3次幂,结果是8。

还需要注意的是,JavaScript遵循运算符优先级规则,这些规则确定表达式中运算符的评估顺序。例如,乘法和除法的优先级高于加法和减法,因此它们首先进行执行:

jsx 复制代码
const result = 10 + 5 * 2; // 先进行乘法运算
console.log(result); // 20

我们可以使用分组运算符()来更改执行的顺序,这在下面的分组运算符部分中进行了介绍。

赋值运算符

赋值运算符 用于将值赋给变量。它们还提供了一种简洁有效的方式,根据表达式或其他值来更新变量的值。除了基本的赋值运算符(=)之外,JavaScript 还提供了复合赋值运算符,它们将算术或逻辑操作与赋值结合在一起。

赋值:=

此运算符用于将一个值赋给一个变量。它允许我们将一个值存储在变量中,以便我们可以在代码中稍后使用和引用它:

jsx 复制代码
const num = 4; // 将值 4 赋给变量 num
const squared = num * num; // 将值 16 赋给变量 squared

赋值运算符将运算符右侧的值分配给左侧的变量。

此外,= 运算符可以链接在一起,以在一行中将相同的值分配给多个变量:

jsx 复制代码
const a = b = c = 10; // 将值 10 分配给变量 a、b 和 c
console.log(a, b, c); // 输出 10 10 10

加法赋值:+=

加法赋值运算符 是一种复合运算符,它执行一步操作和赋值。具体来说,它将右操作数加到左操作数上,然后将结果分配给左操作数:

jsx 复制代码
let num = 10;
num += 5 // 15

这个运算符不仅限于数字。它也可以用于字符串连接:

jsx 复制代码
let greeting = 'Hello, ';
greeting += 'World!' // 'Hello, World!'

当操作数不是相同类型时,JavaScript 会应用与类型强制转换相同的规则,就像我们之前看到的一样:

jsx 复制代码
let greeting = 'Hello, ';
greeting += 42 // 'Hello, 42'

减法赋值:=

减法赋值运算符 是另一种复合运算符,它执行一步操作和赋值。它从左操作数中减去右操作数,然后将结果分配给左操作数:

jsx 复制代码
let num = 10;
num -= 5 // 5

与其他 JavaScript 运算符一样,当操作数不是相同类型时,-= 运算符会在进行比较时进行类型强制转换。如果可以将一个操作数转换为数字,JavaScript 就会这样做:

jsx 复制代码
let num = '10';
num -= 5 // num 现在是 5(数字),而不是 '5'(字符串)

否则,结果是 NaN

jsx 复制代码
let name = 'Jim';
name -= 5 // NaN

乘法赋值:=

乘法赋值运算符 将左操作数乘以右操作数,然后将结果分配回左操作数:

jsx 复制代码
let num = 5;
num *= 3 // 15

当我们使用不同类型的操作数时,JavaScript 会尝试将非数字字符串操作数转换为数字:

jsx 复制代码
let num = '5';
num *= 3 // num 现在是 15(数字),而不是 '15'(字符串)

如果字符串操作数无法转换为数字,则结果为 NaN

除法赋值:/=

与其兄弟运算符一样,除法赋值运算符 在两个操作数上执行操作,然后将结果分配回左操作数:

jsx 复制代码
let num = 10;
num /= 2 // 5

否则,我们在上面关于除法运算符的部分讨论过的规则也适用:

jsx 复制代码
let num = 3;
num /= '-0.5' // -6

num = 3;
num /= 0 // Infinity

num = 3;
num /= 'Jim' // NaN

取模赋值:%=

取模赋值运算符 对两个操作数执行取模运算,然后将结果分配给左操作数:

jsx 复制代码
let num = 10;
num %= 3 // 1

否则,我们在上面关于取模运算符的部分讨论过的规则也适用:

jsx 复制代码
let num = 3;
num %= '3' // 0

num = 3;
num %= 0 // NaN

num = 3;
num %= 'Jim' // NaN

指数赋值:*=

指数赋值运算符执行指数运算,其中左操作数是底数,右操作数是指数,然后将结果分配给左操作数:

jsx 复制代码
let num = 2;
num **= 3 // 8

与之前一样,当第二个操作数不是数字时,JavaScript 将尝试以不同程度的成功进行转换:

jsx 复制代码
let num = 2;
num **= '3' // 8

num = 2;
num **= 'Jim' // NaN

位运算赋值运算符

我们上面一直关注算术运算符,但 JavaScript 还支持在位级别上运作的赋值运算符。这些是位运算赋值运算符。这些运算符包括:

  • 位与赋值(&=
  • 位或赋值(|=
  • 位异或赋值(^=
  • 左移位赋值(<<=
  • 右移位赋值(>>=
  • 无符号右移位赋值(>>>=

这些 JavaScript 赋值运算符中的每一个都执行与操作数的二进制表示的特定位运算,并将结果分配回左操作数。

比较运算符

JavaScript 运算符的另一重要运算符:比较运算符=====。顾名思义,比较运算符 用于比较值并返回布尔结果。比较运算符是许多编程决策和控制结构的基础,从简单的条件检查到复杂的逻辑操作都必不可少。

相等性:==

相等运算符 用于检查两个值是否相等。它返回一个布尔结果。要注意是,此比较运算符执行松散的相等性检查,这意味着如果操作数的类型不同,JavaScript 将尝试将它们转换为公共类型,然后再进行比较:

jsx 复制代码
1 == 1 // true,两个操作数都是数字
1 == '1' // true,字符串被转换为数字

当涉及到对象和数组时,== 运算符检查它们是否引用内存中的相同位置,而不是它们的内容是否相同:

jsx 复制代码
const array1 = [1, 2, 3];
const array2 = [1, 2, 3];
array1 == array2 // false,尽管它们看起来一样

const array3 = array1;
array1 == array3; // true,它们引用相同的内存位置

在这种情况下,JavaScript 不会尝试转换和比较对象或数组中的值。相反,它检查它们是否是相同的对象(即它们是否占用相同的内存空间)。

不等性:!=

不等运算符 用于检查两个值是否不相等。与 == 运算符类似,它执行松散的不等比较。这意味着,如果它们是不同类型,它会尝试将操作数转换为公共类型,然后再进行比较:

jsx 复制代码
1 != 2 // true,1 不等于 2
1 != '1' // false,字符串被转换为数字,1 等于 1
'apple' != 'orange' // true,字符串不同

== 运算符类似,当涉及对象和数组时,!= 运算符检查它们是否引用内存中的相同位置,而不是它们的内容是否相同。

严格相等性 (===) 和严格不等性 (!==)

严格相等性严格不等性 比较运算符类似于它们的非严格对应物 (==!=),但它们不执行类型强制转换。如果操作数是不同类型的,无论它们的值是否相等,它们都被视为不同。

以下是它们的工作原理:

jsx 复制代码
1 === '1' // false,因为 Number 不严格等于 String
1 !== '1' // true,因为 Number 不严格等于 String
null === undefined // false,即使 null == undefined 为 true
true === 1 // false,因为 Boolean 不严格等于 Number

对于对象和数组,严格相等运算符的行为与松散相等运算符相同:它检查它们是否引用相同的对象,而不是它们的内容是否相同。

NaN 是一个特殊情况。它是 JavaScript 中唯一不严格等于自身的值:

jsx 复制代码
NaN === NaN // false

大于:>

大于运算符 检查左操作数是否大于右操作数,返回一个布尔结果。这种比较对数值值来说很简单:

jsx 复制代码
4 > 3 // true
2 > 2 // false

当比较非数值值时,JavaScript 应用一种转换过程,使它们可以进行比较。如果两个值都是字符串,它们将根据它们在 Unicode 字符集中的相应位置进行比较:

jsx 复制代码
'3' > '2' // true
'abc' > 'def' // false

如果一个或两个操作数不是字符串,JavaScript 将尝试将它们转换为比较用的数字:

jsx 复制代码
'10' > 2 // true,将 '10' 转换为数字进行比较

在这种转换过程中,特定值的特殊规则适用。例如,null 被转换为 0undefined 被转换为 NaN,而布尔值 truefalse 分别被转换为 10。但是,如果在转换后任何一个操作数是 NaN,则运算符始终返回 false

jsx 复制代码
10 > 'Jim' // false,将 'Jim' 转换为数字得到 NaN

小于:<

小于运算符 如果左操作数小于右操作数,则返回 true,否则返回 false。与大于运算符一样,只是操作数的顺序相反:

jsx 复制代码
5 < 10 // true,5 小于 10
'10' <

 '2' // true,因为比较是按字典顺序进行的
'10' < 2 // false,字符串 '10' 被强制转换为数字

> 运算符一样,< 运算符在进行比较之前使用强制类型转换将操作数转换为公共类型。

大于等于 (>=) 和小于等于 (<=)

大于等于 (>=) 和 小于等于 (<=) 运算符与它们的 <> 对应物类似,只是多了一个相等条件。

对于 >= 运算符,如果左操作数大于或等于右操作数,则返回 true,否则返回 false。相反,对于 <= 运算符,如果左操作数小于或等于右操作数,则返回 true,否则返回 false。强制类型转换和类型转换规则与上面介绍的 <> 运算符相同:

jsx 复制代码
5 >= 5 // true,5 等于 5
5 >= 6 // false,5 不大于 6
'10' >= '2' // false,'1' 的 Unicode 为 49,而 '2' 的 Unicode 为 50
'10' <= 20 // true,字符串 '10' 被强制转换为数字
5 >= false // true,false 被强制转换为 0
5 <= true // false,true 被强制转换为 1
null >= -1 // true,null 被强制转换为 0
undefined <= 0 // false,undefined 被强制转换为 NaN

逻辑运算符

JavaScript 中的 逻辑运算符 提供了一种同时处理多个条件的方式。它们是编程中决策构造的重要组成部分,例如 if 语句和 for 循环。

逻辑与:&&

当与布尔值一起使用时,逻辑与运算符返回 true,如果所有条件都为 true,否则返回 false

然而,与非布尔值一起使用时,它变得非常有趣:

  • 该运算符从左到右评估条件。
  • 如果它遇到一个可以转换为 false(称为假值)的值,它会停止并返回该值。
  • 如果所有值都为真值,则返回最后一个真值。

例如:

jsx 复制代码
true && true // true
true && false // false
'apple' && 'banana' // 'banana'
'' && 'banana' // ''

&& 运算符返回操作数的值,使其成为条件执行和设置默认值的多功能工具。例如,我们可以使用 && 运算符仅在满足某个条件时执行函数或一段代码:

jsx 复制代码
const userIsLoggedIn = true;
userIsLoggedIn && renderWelcomeMessage();

在这种情况下,只有当 userIsLoggedIntrue 时,才会执行 renderWelcomeMessage。如果 userIsLoggedInfalse,操作将在 userIsLoggedIn 处停止,renderWelcomeMessage 将不会被调用。这种模式在 React 中经常用于有条件地渲染组件。

逻辑或:||

当与布尔值一起使用时,逻辑或运算符返回 true,如果至少一个条件为 true,否则返回 false

它还可以返回非布尔值,执行所谓的短路求值。它从左到右评估条件,停在并返回第一个真值条件的值。如果所有条件都是假值,它将返回最后一个假值:

jsx 复制代码
true || false // true
false || true // true
'Hello' || 'World' // 'Hello'
'' || 'World' // 'World'
0 || '' // ''

逻辑非:!

逻辑非运算符用于反转条件或表达式的布尔值。与 &&|| 运算符不同,! 运算符始终返回布尔值。

如果条件为真值(即可以转换为 true),则该运算符返回 false。如果条件为假值(即可以转换为 false),则该运算符返回 true

jsx 复制代码
!true // false
!false // true
!'Hello' // false
!'' // true
!0 // true

我们可以使用 ! 运算符两次将一个值转换为其布尔等效值:

jsx 复制代码
!!'Hello' // true
!!'' // false
!!0 // false

空值合并运算符:??

空值合并运算符 用于检查其左侧的值是否为 nullundefined,如果是,它将返回右侧的值。否则,它将返回左侧的值。

尽管在某些方面与 || 运算符相似,但 ?? 运算符在处理假值时有所不同。

|| 运算符在左侧操作数为任何假值(如 nullundefinedfalse0NaN'')时会返回右操作数,?? 运算符只在左操作数为 nullundefined 时才会返回右操作数:

jsx 复制代码
null ?? '默认字符串' // '默认字符串'
undefined ?? '默认字符串' // '默认字符串'
'' ?? '默认字符串' // ''
0 ?? 100 // 0

使用逻辑运算符设置默认值

||?? 逻辑运算符在程序中设置默认值时非常有用。下面是使用 || 运算符进行设置默认值的示例:

jsx 复制代码
const userColorPreference = null;
const defaultColor = '蓝色';
const color = userColorPreference || defaultColor; // '蓝色'

这是使用 ?? 运算符的示例:

jsx 复制代码
const userColorPreference = null;
const defaultColor = '蓝色';
const color = userColorPreference ?? defaultColor; // '蓝色'

这些逻辑运算符之间的主要区别(如上所示)在于它们如何处理假值:

jsx 复制代码
const userColorPreference = '';
const defaultColor = '蓝色';
const color1 = userColorPreference || defaultColor; // '蓝色'
const color2 = userColorPreference ?? defaultColor; // ''

位运算符

JavaScript 中的位运算符提供了一种在二进制级别执行操作的方式,直接操作数字的二进制表示。虽然这些运算符在特定任务(如数据编码、解码和处理)中可能很有用,但在日常 JavaScript 编程中并不经常使用。

位与运算符:&

位与运算符 对整数的二进制表示进行位与操作。它返回一个新数字,其中的位如果在两个操作数中的相同位置上都为 1,则设置为 1。否则,将其设置为 0:

jsx 复制代码
// 5 的二进制表示:101
// 3 的二进制表示:011
5 & 3 // 1(对应二进制 001)

位或运算符:|

位或运算符 的工作方式类似于 & 运算符,但它设置为 1 的位,如果操作数中相同位置上的位至少有一个为 1:

jsx 复制代码
// 5 的二进制表示:101
// 3 的二进制表示:011
5 | 3 // 7(对应二进制 111)

位异或运算符:^

位异或运算符 有点不同。它仅在操作数中的相同位置上的位不同(一个为 1,另一个为 0)时设置位为 1:

jsx 复制代码
// 5 的二进制表示:101
// 3 的二进制表示:011
5 ^ 3 // 6(对应二进制 110)

位非运算符:~

位非运算符 (~) 反转其操作数的位。它将二进制表示中的 1 变为 0,0 变为 1:

jsx 复制代码
// 5 的二进制表示:101
~5 // -6(对应二进制的补码,即 010)

注意:二进制补码 是一种表示负整数的二进制符号表示方法。

位移运算符:<<, >>, >>>

位移运算符 用于将二进制数的位向左或向右移动。在 JavaScript 中,有三种类型:左位移 (<<)、右位移 (>>) 和零填充右位移 (>>>)。

左位移位运算符 (<<) 将位向左移动,并在右侧填充零。右位移运算符 (>>) 将位向右移动,舍弃移出的位。零填充右位移运算符 (>>>) 也将位向右移动,但在左侧填充零。

这些运算符在日常 JavaScript 编程中较少使用,但在更专业的领域,如低级编程、二进制数据处理和某些类型的数学计算中有用。

其他运算符

除了常用的算术、比较、逻辑和位运算符外,JavaScript 还提供了一些特定用途的独特运算符。这些包括用于处理条件逻辑、管理对象属性、控制操作顺序等方面的运算符。

条件(三元)运算符:? :

条件三元运算符 (? :) 是在 JavaScript 代码中做决策的一种简洁方式。它因为是唯一接受三个操作数的运算符而得名。这个条件运算符的语法如下:

jsx 复制代码
条件 ? 如果为真执行的表达式 : 如果为假执行的表达式

该运算符首先评估条件。如果条件为 true,则执行 `如果为真执行的表达

,如果条件为 false,则执行 如果为假执行的表达式`:

jsx 复制代码
const age = 15;
const status = age >= 18 ? '成年人' : '未成年人'; // '未成年人'

在上面的代码中,三元运算符检查 age 是否大于或等于 18。由于 age 是 15,条件求值为 false,因此将 '未成年人' 分配给 status 变量。

这个运算符可以是一种方便的方式来编写简洁的 if-else 语句,但如果过度使用或在复杂条件中使用,可能会使代码难以阅读。

扩展运算符:...

扩展运算符 (...) 允许在期望零个或多个参数或元素的位置上展开可迭代对象(如数组或字符串)。它可以用于函数调用、数组字面量和对象字面量中:

jsx 复制代码
// 在函数调用中
const numbers = [1, 2, 3];
console.log(...numbers); // 1 2 3

// 在数组字面量中
const moreNumbers = [4, 5, ...numbers];
console.log(moreNumbers); // [4, 5, 1, 2, 3]

// 在对象字面量中
const obj1 = { a: 1, b: 2 };
const obj2 = { ...obj1, c: 3 };
console.log(obj2); // { a: 1, b: 2, c: 3 }

扩展运算符可以用于创建数组或对象的副本、连接数组或将数组的元素作为参数传递给函数。

逗号运算符:,

逗号运算符 (,) 允许在序列中评估多个表达式,并返回最后一个表达式的结果。这些表达式从左到右进行评估。

当我们需要在只允许一个表达式的位置包含多个表达式时,逗号运算符特别有用,例如在 for 循环的初始化或更新部分:

jsx 复制代码
for(let i = 0, j = 10; i <= 10; i++, j--) {
  console.log(`i: ${i}, j: ${j}`);
}

上面的代码中,逗号运算符用于在 for 循环中声明和更新两个变量 (ij)。

可选链运算符:?.

可选链 是 JavaScript 的一个相对较新的特性(截止到 ES2020),它简化了访问对象深层嵌套属性的过程。它通过提供一种方式来尝试检索属性值,而无需明确检查链中的每个引用是否存在,从而帮助我们编写更干净、更安全的代码:

jsx 复制代码
const user = {
  name: 'Jim',
  address: {
    street: '123 Hochstraße',
    city: 'Munich'
  }
};

user?.address?.city // 'Munich'
user?.contacts?.email // undefined

在上面的示例中,user?.address?.city 尝试访问 user.addresscity 属性,如果 useruser.address 都存在,则返回 city 的值。否则,它将返回 undefined。这种方法避免了 JavaScript 中的一个常见陷阱,即尝试访问 undefinednull 的属性会导致 TypeError

jsx 复制代码
user.contacts.email // Uncaught TypeError: Cannot read properties of undefined (reading 'email')

在可选链之前,JavaScript 开发人员不得不使用冗长的条件逻辑来避免此类错误:

jsx 复制代码
let email;
if (user && user.contacts) {
  email = user.contacts.email;
} else {
  email = '未指定';
}

email // '未指定'

管道运算符:|>

管道运算符 (|>) 旨在提高代码的可读性,该代码否则将使用嵌套函数调用编写。它允许我们获取一个表达式的结果并将其传递给下一个表达式。这在我们对值应用一系列转换时特别有用:

jsx 复制代码
const result = exclaim(capitalize(doubleSay('hello')));
console.log(result);  //=> 'HELLO, HELLO!'

使用管道运算符,我们可以像这样重写这段代码:

jsx 复制代码
const result = 'hello'
  |> doubleSay
  |> capitalize
  |> exclaim;

console.log(result);  //=> 'HELLO, HELLO!'

分组运算符:()

JavaScript 中的分组运算符 (()) 用于更改表达式中评估的优先级顺序。这个运算符不对其值执行任何操作,但它控制了表达式中计算的顺序。

例如,乘法和除法的优先级高于加法和减法。这意味着,在表达式 2 + 3 * 4 中,首先执行乘法,得到 2 + 12,然后执行加法,得到 14

如果我们想改变操作顺序,可以使用分组运算符。例如,在前面的示例中,如果我们希望加法在乘法之前执行,可以编写 (2 + 3) * 4。在这种情况下,首先执行加法,得到 5 * 4

,然后执行乘法,得到 20

分组运算符允许我们确保按照我们打算的顺序执行操作,这在更复杂的数学或逻辑表达式中非常重要。

结论

在本文中,我们深入研究了 JavaScript 运算符的广泛且有时复杂的世界。这些运算符使我们能够操作数据、控制程序流程并进行复杂的计算。

了解这些运算符不仅仅是一种学术性的练习;它是一种实际的技能,可以提高我们编写和理解 JavaScript 代码的能力。

还记得我们一开始提到的令人困惑的代码段吗?让我们重新看一下,看看它现在是否更容易理解:

jsx 复制代码
const x = 10, y = 20, z = 30;
console.log((x > y ? x : y) > z ? (x > y ? x : y) : z);

用通俗的语言来说,这段代码找到了三个数字 xyz 中的最大值。

它的工作原理如下:

  1. 表达式 (x > y ? x : y) 检查 x 是否大于 y
  2. 如果 x 大于 y,它返回 x;否则,返回 y。换句话说,它获取 xy 的最大值。
  3. 将这个结果(xy 的最大值)与 z 使用 > 运算符进行比较。
  4. 如果 xy 的最大值大于 z,则再次评估 (x > y ? x : y)
  5. 在这个三元表达式中,再次比较 xy,并返回较大的值。
  6. 否则,如果 z 大于 xy 的最大值,那么 z 就是这三个数字的最大值,并将其返回。

嵌套三元运算符这样不容易阅读,可以使用 Math.max 更好地表达这个计算:

jsx 复制代码
Math.max(x, y, z) // 30

尽管如此,理解 JavaScript 运算符的工作方式就像学习一门新语言的语法。起初可能有挑战,但一旦掌握了基础,就可以轻松地构建复杂的表达式,愉快的去装逼了。

相关推荐
zhanghaisong_201523 分钟前
Caused by: org.attoparser.ParseException:
前端·javascript·html·thymeleaf
Eric_见嘉26 分钟前
真的能无限试(白)用(嫖)cursor 吗?
前端·visual studio code
DK七七1 小时前
多端校园圈子论坛小程序,多个学校同时代理,校园小程序分展示后台管理源码
开发语言·前端·微信小程序·小程序·php
老赵的博客1 小时前
QSS 设置bug
前端·bug·音视频
Chikaoya1 小时前
项目中用户数据获取遇到bug
前端·typescript·vue·bug
南城夏季1 小时前
蓝领招聘二期笔记
前端·javascript·笔记
Huazie1 小时前
来花个几分钟,轻松掌握 Hexo Diversity 主题配置内容
前端·javascript·hexo
NoloveisGod2 小时前
Vue的基础使用
前端·javascript·vue.js
GISer_Jing2 小时前
前端系统设计面试题(二)Javascript\Vue
前端·javascript·vue.js
喔喔咿哈哈2 小时前
【手撕 Spring】 -- Bean 的创建以及获取
java·后端·spring·面试·开源·github