likes
comments
collection
share

全网最全JavaScript运算符指南

作者站长头像
站长
· 阅读数 13

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

JavaScript运算符是什么?

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

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首先将两个操作数转换为原始值。完成此操作后,它会检查两个操作数的类型。

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

'Hello, ' + 'World!' // Hello, World!
'The number is ' + 42 // 'The number is 42'

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

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

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

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

10 + 20 // 30
10 + true // 11 — true会转换为值1

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

1 + { a: 1 } // '1[object Object]'

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

减法:``

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

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

10 - 3 // 7
'100' - 30 // 70

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

const num1 = BigInt('9007199254740993');
const num2 = BigInt('3');
num1 - num2 // 900719925474

0990n

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

10 - 'Jim' // NaN

乘法:

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

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

10 * 5 // 50

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

const num1 = 9007199254740993n;
num1 * 2n // 18014398509481986n

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

'100' * 30 // 3000
10 * 'Jim' // NaN

除法:/

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

标准数值除法:

10 / 2 // 5
10 / '2' // 5

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

const num = 10n;
num / 3n // 3n,而不是3.333...n

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

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

模数(余数):%

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

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

10 % 3 // 1
'10' % 3 // 1

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

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

const isEven = num => num % 2 === 0;
isEven(1) // false
isEven(2) // true

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

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

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

增量:++

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

后缀增量

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

let num = 5;
const result = num++;
console.log(result); // 5
console.log(num); // 6

前缀增量

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

let num = 5;
const result = ++num;
console.log(result); // 6
console.log(num); // 6

减量:``

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

后缀减量

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

let num = 5;
const result = num--;
console.log(result); // 5
console.log(num); // 4

前缀减量

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

let num = 5;
const result = --num;
console.log(result); // 4
console.log(num); // 4

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

const num = 5;
const result = num--; // Uncaught TypeError: Assignment to constant variable.

其他算术运算符

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

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

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

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

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

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

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

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

赋值运算符

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

赋值:=

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

const num = 4; // 将值 4 赋给变量 num
const squared = num * num; // 将值 16 赋给变量 squared

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

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

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

加法赋值:+=

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

let num = 10;
num += 5 // 15

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

let greeting = 'Hello, ';
greeting += 'World!' // 'Hello, World!'

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

let greeting = 'Hello, ';
greeting += 42 // 'Hello, 42'

减法赋值:=

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

let num = 10;
num -= 5 // 5

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

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

否则,结果是 NaN

let name = 'Jim';
name -= 5 // NaN

乘法赋值:=

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

let num = 5;
num *= 3 // 15

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

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

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

除法赋值:/=

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

let num = 10;
num /= 2 // 5

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

let num = 3;
num /= '-0.5' // -6

num = 3;
num /= 0 // Infinity

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

取模赋值:%=

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

let num = 10;
num %= 3 // 1

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

let num = 3;
num %= '3' // 0

num = 3;
num %= 0 // NaN

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

指数赋值:*=

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

let num = 2;
num **= 3 // 8

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

let num = 2;
num **= '3' // 8

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

位运算赋值运算符

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

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

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

比较运算符

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

相等性:==

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

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

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

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

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

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

不等性:!=

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

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

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

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

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

以下是它们的工作原理:

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

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

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

NaN === NaN // false

大于:>

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

4 > 3 // true
2 > 2 // false

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

'3' > '2' // true
'abc' > 'def' // false

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

'10' > 2 // true,将 '10' 转换为数字进行比较

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

10 > 'Jim' // false,将 'Jim' 转换为数字得到 NaN

小于:<

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

5 < 10 // true,5 小于 10
'10' <

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

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

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

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

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

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(称为假值)的值,它会停止并返回该值。
  • 如果所有值都为真值,则返回最后一个真值。

例如:

true && true // true
true && false // false
'apple' && 'banana' // 'banana'
'' && 'banana' // ''

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

const userIsLoggedIn = true;
userIsLoggedIn && renderWelcomeMessage();

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

逻辑或:||

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

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

true || false // true
false || true // true
'Hello' || 'World' // 'Hello'
'' || 'World' // 'World'
0 || '' // ''

逻辑非:!

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

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

!true // false
!false // true
!'Hello' // false
!'' // true
!0 // true

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

!!'Hello' // true
!!'' // false
!!0 // false

空值合并运算符:??

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

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

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

null ?? '默认字符串' // '默认字符串'
undefined ?? '默认字符串' // '默认字符串'
'' ?? '默认字符串' // ''
0 ?? 100 // 0

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

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

const userColorPreference = null;
const defaultColor = '蓝色';
const color = userColorPreference || defaultColor; // '蓝色'

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

const userColorPreference = null;
const defaultColor = '蓝色';
const color = userColorPreference ?? defaultColor; // '蓝色'

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

const userColorPreference = '';
const defaultColor = '蓝色';
const color1 = userColorPreference || defaultColor; // '蓝色'
const color2 = userColorPreference ?? defaultColor; // ''

位运算符

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

位与运算符:&

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

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

位或运算符:|

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

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

位异或运算符:^

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

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

位非运算符:~

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

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

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

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

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

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

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

其他运算符

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

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

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

条件 ? 如果为真执行的表达式 : 如果为假执行的表达式

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

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

const age = 15;
const status = age >= 18 ? '成年人' : '未成年人'; // '未成年人'

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

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

扩展运算符:...

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

// 在函数调用中
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 循环的初始化或更新部分:

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

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

可选链运算符:?.

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

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

user.contacts.email // Uncaught TypeError: Cannot read properties of undefined (reading 'email')

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

let email;
if (user && user.contacts) {
  email = user.contacts.email;
} else {
  email = '未指定';
}

email // '未指定'

管道运算符:|>

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

const result = exclaim(capitalize(doubleSay('hello')));
console.log(result);  //=> 'HELLO, HELLO!'

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

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 代码的能力。

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

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 更好地表达这个计算:

Math.max(x, y, z) // 30

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