CSC-NOTESCSC-NOTES
首页
  • 前端笔记

    • Vue
    • React
    • CSS
    • JavaScript
    • TypeScript
  • 服务端笔记

    • NodeJS
  • C/C++

    • C语言
  • 数据库笔记

    • Postgresql
  • 计算机网络

    • 计算机网络基础
    • 计算机网络进阶
  • 操作系统

    • 操作系统基础
    • 操作系统进阶
  • 前端工程化

    • Vue
    • React
  • 后端工程化

    • NodeJS
  • 数据结构
  • 算法
  • 前端面试
  • 后端面试
Github
首页
  • 前端笔记

    • Vue
    • React
    • CSS
    • JavaScript
    • TypeScript
  • 服务端笔记

    • NodeJS
  • C/C++

    • C语言
  • 数据库笔记

    • Postgresql
  • 计算机网络

    • 计算机网络基础
    • 计算机网络进阶
  • 操作系统

    • 操作系统基础
    • 操作系统进阶
  • 前端工程化

    • Vue
    • React
  • 后端工程化

    • NodeJS
  • 数据结构
  • 算法
  • 前端面试
  • 后端面试
Github
  • JavaScript
    • JavaScript基础
      • 1、语法基础
        • 1.1语法
        • 1.2变量
        • 1.3数据类型
        • 1.4操作符
        • 1.5语句
    • JavaScript高级
      • this指向问题
      • 作用域和闭包
      • 变量和函数提升

JavaScript操作符

ECMA-262描述了一组可用于操作数据值的操作符,包括数学操作符(如加、减)、位操作符、关系操作符和相等操作符等。ECMAScript中的操作符是独特的,因为它们可用于各种值,包括字符串、数值、布尔值、甚至还有对象。对于对象,操作符通常会调用valueOf()和/或toString()方法来取得可计算的值。

1.一元操作符

只操作一个值的操作符叫一元操作符。一元操作符是ECMAScript中最简单的操作符。

1.1 递增/递减操作符

递增和递减操作符直接照搬自C语言,但有两个版本:前缀版和后缀版

前缀版

let age = 29;
++age;

这个例子,前缀递增操作符把age的值变成了30(给之前的值29加1)。因此实际等于如下表达式。

let age = 29;
age = age + 1;

前缀递减操作符也是类似。

let age = 29;
--age;

执行操作后,变量age的值变成了28。

无论是前缀递增还是前缀递减,变量的值都会在语句被求值之前改变。

let age = 29;
let age1 = --age + 2;

console.log(age); // 28
console.log(age1); // 30

变量age1以age减1后的值再加上2进行初始化。因为递减操作符先发生,所以age的值先变成28,然后再加2,结果是30。

前缀递增和递减在语句中的优先级是相等的,因此会从左到右依次执行。

let num1 = 2;
let num2 = 20;
let num3 = --num1 + num2;
let num4 = num1 + num2;
console.log(num3); // 21
console.log(num4); // 21

后缀版

递增和递减后缀版语法一样(分别是++和--),只不过要放到变量后面。后缀版与前缀版的主要区别在于,后缀版递增和递减在语句被求值后才发生。在某些情况下,这种差异没什么影响。

let age = 29;
age++; // 30

把递增操作符放到变量后面不会改变语句执行的结果,因为递增是唯一的操作。可是,再跟其他操作混合时,差异就会很明显。

let num1 = 2;
let num2 = 20;
let num3 = num1-- + num2;
let num4 = num1 + num2;
console.log(num3); // 22
console.log(num4); // 21

这四个操作符可以作用于任何值,意思就是不限于整数、字符串、布尔值、浮点值、甚至对象都可以。递增和递减遵循以下规则。

  • 对于字符串,如果是有效的数值形式,则转化为数值再应用改变。变量类型从字符串变为数值类型。
  • 对于字符串,如果不是有效的数值形式,则将变量的值设置为NaN。变量类型从字符串变为数值类型。
  • 对于布尔值,如果是false,则转化为0再应用改变。变量类型转变为数值类型。
  • 对于布尔值,如果是true,则转化为1再应用改变。变量类型转变为数值类型。
  • 对于浮点值,加1或减1。
  • 对于对象,则调用其valueOf()方法取得可以操作的值。对得到的值应用上述规则。如果是NaN,则调用toString()并再次应用上述规则。变量类型从对象转变为数值。
let a = '2';
let b = 'Tom';
let c = false;
let d = true;
let e = 1.1;
let o = {
  valueOf() {
    return -1;
  }
}
console.log(++a); // 结果为3
console.log(++b); // 结果为NaN
console.log(++c); // 结果为1
console.log(++d); // 结果为2
console.log(++e); // 结果为1.1
console.log(++o); // 结果为0

1.2一元加和减

一元加和减操作符对大多数开发者来说并不陌生,它们在ECMAScript中跟在高中数学中的用途一样。

一元加由一个加号表示(+),放在变量前头,对数值没有任何影响。

let num = 25;
num = +num;
console.log(num); // 25

如果将一元加应用到非数值。则会执行与使用Number()转型函数一样的类型转换:布尔值转化为0或1,字符串进行特殊解析,对象会调用它们的valueOf()和/或toString()方法得到的值。

let str1 = '01';
let str2 = '1.1';
let str3 = 'Tom';
let b = false;
let f = 1.1;
let o = {
  valueOf() {
    return -1;
  }
}
str1 = +str1; // 结果为1
str2 = +str2; // 结果为1.1
str3 = +str3; // 结果为NaN
b = +b; // 结果为0
f = +f; // 结果为 1.1
o = +o; // 结果为 -1

一元减由一个减号表示(-),放在变量前头,主要用于把数值变为负值。如把1转变为-1。

let num = 25;
num = -num;
console.log(num); // -25

一元减遵循与一元加同样的规则,先进行转化,然后再取负值。

一元加和减操作符主要用于基本算数,也可以用于数据类型转化。

2.位运算符

下面要介绍的的操作符用于数值的底层操作,也就是操作内存中表示数据的比特(位)。ECMAScript中的所有数值都以IEEE 75464位格式存储,但位操作并不直接应用到64位表示,而是先把值转化为32位整数,再进行位操作,之后再把结果转为64位。对于开发者而言,就像在处理32位整数一样,因为64位整数存储格式是不可见的。所以只需要考虑32位整数即可。

有符号整数使用32位的前31位表示整数值。第32位表示数值的符号,如0表示正、1表示负。这一位称为符号位,它的值决定了数值其余部分的格式。正值以真正的二进制格式储存,即31位中的每一位都代表2的幂。第一位(称为第0位)表示2º,第二位表示2¹,一次类推。如果一个位是空的,则以0填充,相当于忽略不计。比如,数值18的二进制格式为00000000000000000000000000010010,或者更简洁的10010。后者是用到的5个有效位,决定了实际值。

负值以一种称为二补数的二进制编码存储。一个数值的二补数通过如下三个步骤计算得到

  • 确定绝对值的二进制表示(如,对于-18,先确定18的二进制表示)。
  • 找到数值的一个补数,换句话说,就是每个0都变成1,每个1都变成0。
  • 给结果加1。

基于上述步骤确定-18的二进制表示,首先从18的二进制开始

那么,-18的二进制就是11111111111111111111111111101110。要注意的事,在处理有符号整数时,我们无法访问第31位。

ECMAScript会帮我们记录这些信息。在把负值输出为一个二进制字符串时,会得到一个前面加了负号的绝对值。

let num = -18;
console.log(num.toString(2)); // -10010

在将-18转化为二进制字符串时,结果得到-10010。转化过程会求得二补数,然后再以更符合逻辑的形式表达出来。

注意

默认情况下,ECMAScript中的所有整数都表示为有符号数。不过,确实存在无符号整数。对于无符号整数来说,第32不表示符号,因为只有正值。无符号整数比有符号整数的范围更大,因为符号位被用来表示数值了。

在对ECMAScript中的数值应用位操作符时,后台会发生:64位数值会转化为32位数值,然后执行位操作,最后再把结果从32为转为64位存储起来。但这个转化导致了一个奇特的副作用,即特殊值NaN和Infinity在位操作中都会被当做0处理。

如果将位操作符应用到非数值,那么会首先使用Number()函数将该值转化为数值(过程是自动的),然后再应用位操作。最终结果是数值。

有符号整数与无符号整数区别

  • 有符号整数(如 Int32)使用最高位作为符号位,可表示负数。
  • 无符号整数(如 Uint32)将所有位视为数值位,只能表示非负数,但范围更大(0 到 2³²-1,即 0 到 4,294,967,295)。

2.1按位非

按位非操作符用波浪号表示(~),他的作用是返回数值的补数。

let num1 = 25; // 00000000000000000000000000011001
let num2 = ~num1; // 11111111111111111111111111100110
console.log(num2); // -26

这里,按位非操作符作用25,得到的结果是-26,按位非得最终效果是对数值取反并减1。类似如下操作

let num1 = 25;
let num2 = -num1 - 1;
console.log(num2); // -26

实际上,尽管两者的结果是一样的,但按位操作的速度快得多,这是因为位操作是在数值的底层表示完成的。

2.2按位与

按位与操作符用和号表示(&),有两个操作数。本质上,按位与就是将两个操作数的每一位对齐,然后基于真值表中的规则,对每一位执行相应的操作。

第一个数值的位第二个数值的位结果
111
100
010
000

按位与操作在两个位都是1返回1,在任何以为0则返回0。

如下例子

let result = 25 & 3;
console.log(result); // 1

25和3的按位与操作的结果是1。这是为啥呢?

如上图所示,25和3的二进制表达中,只有第0位上的两位数字都是1。于是结果数值的所有其他位都会以0补充,因此结果就是1。

2.3按位或

按位或操作符用管道符(|)表示,同样有两个操作数。

第一个数值的位第二个数值的位结果
111
101
011
000

按位或操作在至少1位是1时返回1,两个都是0时返回0。

let result = 25 | 3;
console.log(result); // 27

可见25和3的按位或的操作结果是27。

2.4按位异或

按位异或用脱字符(^)表示。

第一个数值的位第二个数值的位结果
110
101
011
000

按位异或与按位或的区别是,它只在一位上是1是返回1(两位都是1或0,则返回0)。 对数值25和3执行按位异或操作:

let result = 25 ^ 3;
console.log(result); // 26

可见按位异或25和3的结果是26。

2.5左移

左移操作符用两个小于号表示(<<),会按照指定的位数将数值的所有位向左移动。比如,如果数值2(二进制10)向左移动5位,就会得到64(二进制10000000)。

let num = 2; // 也就是 二进制10
let num1 = 2 << 5; // 也就是二进制 1000000 就是10进制64
console.log(num1); // 64

注意

左移会保留它所操作数值的符号。比如,-2左移5位,将得到-64,而不是正64

2.6有符号右移

有符号右移由两个大于号表示(>>),会将数值的所有32位向右移,同时保留符号(正或负)。

有符号的右移实际上是左移的逆运算。比如,将64右移5位得到2。

let num = 64;
console.log(num >> 5); // 2

2.7无符号右移

无符号右移用三个大于号表示(>>>),会将数值的所有32位都向右移。对于正数,无符号右移与有符号右移结果相同。对于负数,有时候差异会非常大。无符号右移会给空位补0,而不管符号位是什么。

3. 布尔操作符

对于编程来说,布尔操作符跟相等操作同等重要。如果没有能力测试这两个值的关系,那么像if-else和循环这样的语句也没什么用了。布尔操作符一共有三个:逻辑非、逻辑与、逻辑或。

3.1 逻辑非

逻辑非操作符由一个叹号(!)表示,可以应用ECMAScript中的任何值。这个操作符始终返回布尔值,无论应用到的是什么数据类型。逻辑非操作符首先将操作数转化为布尔值,然后再取反。

  • 如果操作数是对象,则返回 false
  • 如果操作数是空字符串,则返回 true
  • 如果操作数是非空字符串,则返回 false
  • 如果操作数是数值0,则返回 false
  • 如果操作数是非0数值(包括 Infinity),则返回 true
  • 如果操作数是null,则返回 true
  • 如果操作数是NaN,则返回 true
  • 如果操作数是undefined,则返回 true
console.log(!false); // true
console.log(!"Tom"); // false
console.log(!0); // true
console.log(!NaN); // true
console.log(!""); // true
console.log(!123); // false

逻辑非操作符也可以用于将任意值转成布尔值。同时使用两个叹号(!!),相当于调用了转型函数 Boolean()。无论操作数是什么类型,第一个叹号会返回布尔值。第二个叹号对该布尔值取反,从而给出变量真正对应的布尔值。结果与 Boolean() 函数一样。

3.2 逻辑与

逻辑与操作符用两个和号表示(&&),应用到两个值

let result = true && false;
第一个操作数第二个操作数结 果
truetruetrue
truefalsefalse
falsetruefalse
falsefalsefalse

逻辑与操作符可用于任何类型的操作数,不限于布尔值。如果有操作数不是布尔值,则逻辑与并不一定返回布尔值。

  • 如果第一个操作数是对象,则返回第二个操作数
  • 如果第二个操作数是对象,则只有第一个操作数求值为true才会返回该对象
  • 如果两个操作数都是对象,则返回第二个操作数
  • 如果有一个操作数是null,则返回null
  • 如果有一个操作数是NaN,则返回NaN
  • 如果有一个操作数是undefined,则返回undefined

逻辑与操作符是一种短路操作符,意思就是说如果第一个操作数决定了结果,那么永远不会对第二个操作数求值。对逻辑与操作符来说,如果第一个操作数是false,那么无论第二个操作数是什么值,结果也不可能等于true。

let found = true;
let result = found && age; // age 在这里未声明
console.log(result); // 不会执行这一行

上面代码之所以会报错,时因为age没有实现声明,所以当逻辑与操作符对它操作就会报错,如果found的值是false,那么就不会报错。

let found = false;
let result = found && age; // age 未声明
console.log(result); // false

因为第一个操作数found = false,逻辑与也不会对它求值。因为此时对 && 右边的操作没有意义。在使用逻辑与操作符时,一定要记得这个短路特性。

3.3 逻辑非

逻辑非由两个管道符表示(||)。

let result = true || false;
第一个操作数第二个操作数结 果
truetruetrue
truefalsetrue
falsetruetrue
falsefalsefalse

与逻辑与类似,如果有一个操作数不是布尔值,逻辑非也不一定返回布尔值。

  • 如果第一个操作数是对象,则返回第一个操作数
  • 如果第一个操作数求值是false,则返回第二个操作数
  • 如果两个操作数都是对象,则返回第二个操作数
  • 如果两个操作数都是null,则返回null
  • 如果两个操作数都是NaN,则返回NaN
  • 如果两个操作数都是undefined,则返回undefined

同样与逻辑与相似,逻辑或操作符也具有短路性,只不过对于逻辑或来说,第一个操作数求值为true,第二个操作数就不会再被求值了。

let found = true;
let result = found || age; // 未声明
console.log(result); // true

跟前面的例子一样,变量age没有声明,但是,因为变量found = true,所以逻辑或不会对age求值,而是直接返回true,如果让found = false,那么就会报错了。

利用这个行为,可以避免给变量赋值null或undefined。

4. 乘性操作符

ECMAScript定义了3个乘性操作符:乘法、除法、取模。在处理非数值时,会包含一些自动的类型转换,在后台被使用 Number() 转型函数处理转成数值。这意味着空字符串会被转成0,布尔值true会被当成1。

4.1 乘法操作符

乘法操作符由一个星号(*)表示,可以用于计算两个数值的乘积,不过乘法操作符在处理特殊值时也有一些特殊行为。

  • 如果操作数都是数值,则执行常规的乘法操作,如果结果超出了ECMAScript规定的值,则返回Infinity或-Infinity
  • 如果有任意操作数是NaN,则返回NaN
  • 如果是Infinity乘以0,则返回NaN
  • 如果是Infinity乘以非0的有限值,则根据第二个操作数的符号返回Infinity或-Infinity
  • 如果是Infinity乘以Infinity,则返回Infinity
  • 如果有不是数值的操作数,则先转为数值,然后再应用上述规则

4.2 除法操作符

除法操作符用斜杠(/)表示,用于计算第一个操作符与第二个操作符的商。

  • 如果操作符都是数值,则执行常规除法运算,如果不能表示商则返回 Infinity或-Infinity
  • 如果有任一操作符为NaN,则返回NaN
  • 如果Infinity除以Infinity,则返回NaN
  • 如果是0除以0,则返回NaN
  • 如果是非0的有限值除以0,则根据第一个操作符的符号返回Infinity或-Infinity
  • 如果是Infinity除以任何数值,则根据第二个操作符的符号返回Infinity或-Infinity
  • 如果有不是数值的操作数,则先使用Number()函数将其转化为数值,然后再应用上述规则

4.3 取模操作符

取模操作符由一个 % 表示。

  • 如果操作数是数值,则执行常规除法运算,返回余数
  • 如果被除数是无限值,除数是有限值,返回NaN
  • 如果被除数是有限值,除数是0,返回NaN
  • 如果是Infinity除以Infinity,返回NaN
  • 如果被除数是有限值,除数是无限值,则返回被除数
  • 如果被除数是0,除数不是0,则返回0
  • 如果有不是数值的操作数,则先使用Number()函数将其转化为数值,然后再应用上述规则

5. 指数操作符

ECMAScript7新增了指数操作符,Math.pow() 现在有了自己的操作符 **。结果是一样的

console.log(Math.pow(3, 2)); // 9
console.log(3**2); // 9

不仅如此,指数操作符也有自己的指数赋值操作符 **=。

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

6. 加性操作符

加性操作符,即加法和减法操作符,除了简单计算加法和减法外,这两个操作符拥有一些特殊行为。与乘性操作符类似,加性操作符在后台会发生不同数据类型的转化。

6.1 加法操作符

加法操作符(+)用于求两数之和。

如果两个操作数都是数值,加法操作符遵循以下规则。

  • 如果有任一操作数是NaN,返回NaN
  • 如果是Infinity加Infinity,返回Infinity
  • 如果是-Infinity加-Infinity,返回-Infinity
  • 如果是Infinity加-Infinity,返回NaN
  • 如果是+0 加 +0,返回 +0
  • 如果是-0 加 +0,返回 +0
  • 如果是-0 加 -0,返回 -0

不过有的操作数是字符串,则应用一下规则

  • 如果两个操作数都是字符串,则将第二个字符串拼接到第一个字符串后面
  • 如果只有一个操作数是字符串,则将另一个操作数转化为字符串,再将两个字符串拼接在一起

如果任一操作数是对象、数值或布尔值,则调用它们的toString()方法以获取字符串,然后再应用以上规则。对于 undefined、null则调用String()函数获取 "undefined","null"。

6.2 减法操作符

减法操作符(-)也是使用很频繁的一种操作符。

与加法操作符一样,减法操作符也有一组规则。

  • 如果两个操作数都是数值,则执行数学减法运算并返回结果
  • 如果有任一操作数是NaN,则返回NaN
  • 如果是Infinity 减 Infinity,则返回NaN
  • 如果是-Infinity 减 -Infinity,则返回NaN
  • 如果是Infinity 减 -Infinity,则返回Infinity
  • 如果是-Infinity 减 Infinity,则返回-Infinity
  • 如果是+0 减 +0,则返回+0
  • 如果是+0 减 -0,则返回-0
  • 如果是-0 减 -0,则返回+0
  • 如果有任一操作数是字符串、布尔值、null、undefined,则先在后台使用Number()将其转化为数值,然后再根据前面的规则执行数学运算。如果转化结果是NaN,则减法计算的结果是NaN
  • 如果有任一操作数是对象,则调用其valueOf()方法取得表示它的数值。如果该值是NaN,则减法计算的结果是NaN。如果对象没有valueOf()方法,则调用其toString()方法,然后再将得到的字符串转化为数值
let num1 = 5 - true; // true被转化为 1,所以结果是4
let num2 = NaN - 1; // NaN
let num3 = 5 - 3; // 2
let num4 = 5 - ""; // ""被转化为 0,所以结果是 5
let num5 = 5 - "2"; // "2"被转化为 2,所以结果是 3
let num6 = 5 - null; // null被转化为 0,所以结果是 5

7. 关系操作符

关系操作符执行比较两个值的操作,包括小于(<)、大于(>)、小于等于(<=)、大于等于(>=)

let result = 5 > 3; //  true
let result2 = 5 < 3; // false

与其他操作符类似,遇到不同数据类型时,也会发生类型转化和其他行为

  • 如果操作数值都是数值,则执行数值比较
  • 如果操作数都是字符串,则逐个比较字符串中对应字符的编码
  • 如果有任一操作数是数值,则将另一个操作数转化为数值,执行数值比较
  • 如有有任一操作数是对象,则调用其valueOf()方法,取得结果后再根据上述规则进行比较,如果没有valueOf()操作符,则调用toString()方法,取得结果后再应用以上规则
  • 如果有任一操作数是布尔值,则将其转化为数值再进行比较

在使用关系操作符比较两个字符串时,很多人认为小于意味着“字母顺序靠前”,而大于意味着“字母顺序靠后”,实际上不是这么回事。对于字符串而言,关系操作符会比较字符串中对应字符的编码,而这些编码是数值。比较完之后,会返回布尔值。问题的关键在于,大写字母的编码都小于小写字母的编码,因此会有以下情况发生。

let result = 'Brick' < 'alphabet'; // true

在这里,字符串“Brick”被认为小于字符串“alphabet”,因为字母B的编码是66,字母a的编码是97。要得到确实按字母顺序比较的结果,就必须把两者都转化为相同的大小写形式(全大写或全小写),然后再进行比较。

let result = "Brick".toLowerCase() < "alphabet".toLowerCase(); // false

将两个操作数都小写,就能保证按照字母表顺序进行判定

另一个奇怪的现象是在比较两个数值字符串的时候

let result = '23' < '3'; // true

这里比较字符串“23”和“3”时返回true。因为两个操作数都是字符串,所以会逐个比较他们的字符编码(字符“2”的编码是50,而字符串“3”的编码是51)。不过,如果有一个操作数是数值,那么比较的结果就正确了。

let result = '23' < 3; // false

因为这次会将字符串“23”转化为数值23,然后再跟数值3进行比较,结果当然就正确了。只要是数值和字符串比较,字符串都会先被转化为数值,然后进行比较。对于数值字符串而言,这样能保证结果正确。但如果字符串不能转化为数字呢!

let result = "a" < 3; // false

因为字符串“a”不能转化为任何有意义的数值,所以只能转化为NaN。这里有一个规则,任何关系操作符在涉及比较NaN时都返回false。这样一来下面例子就有趣了。

let reuslt1 = NaN < 3; // false
let result2 = NaN >= 3; // false

在大多数情况下,如果一个值不小于另一个值,那就一定大于或等于它,但在比较NaN时,无论是小于还是大于等于,比较的结果都返回false。

8. 相等操作符

判断两个变量是否相等是编程中最重要的操作之一。在比较字符串、数值和布尔值是否相等时,过程都很直观。但是在比较两个对象相等时,情况就比较复杂了。ECMAScript中的相等和不相等操作符,原本在比较之前会执行类型转化,但很快就有人质疑这种转化是否应该发生。最终,ECMAScript提供了两组操作符。第一组是等于和不等于,它们在比较之前执行转化。第二组是全等和不全等,他们比较之前不执行转化。

8.1 等于和不等于

ECMAScript中的等于操作符用两个等号表示(==),如果操作数相等,则返回true。不等于操作符用叹号和等于号(!=)表示,如果两个操作数不相等,则返回true。这两个操作符都会先进行类型转化(通常称为强制类型转化)再确定操作数是否相等。 在转化操作数的类型时,相等和不等遵循以下规则

  • 如果任意操作数是布尔值,则将其转化为数值再比较是否相等。false转化为0,true转化为1
  • 如果一个操作数是字符串,另一个操作数是数值,则尝试将字符串转化为数值,再比较是否相等
  • 如果一个操作数是对象,另一个操作数不是,则调用对象的valueOf()方法取得其原始值,再根据以上规则进行比较

在进行比较时,这两个操作符会遵循以下规则

  • null和undefined相等
  • null和undefined不能转化为其他类型的值再进行比较
  • 如果有任一操作数是NaN,则相等操作符返回false,不等操作符返回true。记住:即使两个操作数都是NaN,相等操作符也返回false,按照规则,NaN不等于NaN
  • 如果两个操作数都是对象,则比较他们是不是同一个对象。如果两个操作数都指向同一个对象,则相等操作符返回true,否则两者不等。

下表总结了一些特殊情况的比较结果

表达式
说明
结果
null == undefined
null 和 undefined 在双等号比较中被视为相等
true
"NaN" == NaN
字符串"NaN"与NaN不相等,NaN与任何值都不相等,包括自身
false
5 == NaN
NaN与任何值都不相等,包括自身
false
NaN == NaN
NaN与任何值都不相等,包括自身
false
NaN != NaN
由于NaN与自身不相等,因此这个比较结果为true
true
false == 0
布尔值false在比较时会转换为数字0
true
true == 1
布尔值true在比较时会转换为数字1
true
true == 2
布尔值true转换为数字1,与2不相等
false
undefined == 0
undefined不与任何值相等,除了null
false
null == 0
null不与任何值相等,除了undefined
false
"5" == 5
字符串"5"在比较时会转换为数字5
true

8.2 不等和不全等

全等和不全等与等于和不等于类似,只不过它们不进行类型转化,全等操作符由3个等号(===)表示,只有两个操作数在不转化的情况下相等才返回true。

let result1 = ("55" == 55); // true
let result2 = ("55" === 55); // false

在这个例子中,第一个比较使用相等操作符,比较的是字符串“55”和数值55。因为相等会进行类型转化,所以 55==55 true,而全等则不进行类型转化,字符串当然和数值不等了所以 false。

不全等操作符使用一个叹号和两个等号(!==)表示,只有两个操作数在不进行类型转化的时候不等才返回true。

let result1 = ("55" != 55); // false
let result2 = ("55" !== 55); // true

另外,虽然null == undefined是true,但null === undefined是false,因为它们不是相同的数据类型。

敲黑板

由于相等和不相等操作符存在类型转化问题,因此推荐使用全等和不全等操作符。这样有助于在代码中保持数据类型的完整性

9. 条件操作符

条件操作符是ECMAScript中用途最广泛的操作符之一

variable = boolean_expression ? true_value : false_value (三元运算符)

上面代码执行了条件赋值操作,即根据条件表达式 boolean_expression 的值取决于将那个值赋值给变量 variable 。如果 boolean_expression 是true,则赋值 true_value; 如果 boolean_expression 是false,则赋值 false_value。

10. 赋值操作符

简单的赋值用等号(=)表示,将右边的值赋值给左边的变量

let num = 10;

复合赋值使用乘性、加性或位操作符后跟等号(=)表示。这些赋值操作符是类似如下常见赋值操作的简写方式。

let num = 10;
num = num + 10;
let num = 10;
num += 10;

每个数学操作符以及其他一些操作符都有对应的复合赋值操作符。

  • 乘后赋值(*=)
  • 除后赋值(/=)
  • 取模后赋值(%=)
  • 加后赋值(+=)
  • 减后赋值(-=)
  • 左移后赋值(<<=)
  • 右移后赋值(>>=)
  • 无符号右移后赋值(>>>=)

这些操作符仅仅是简便写法,使用它们不会提高性能

11. 逗号操作符

逗号操作符可以用来在一条语句中执行多个操作

let num1 = 1, num2 = 2, num3 = 3;

在一条语句中同时声明多个变量是逗号操作符常用的场景。不过也可以用逗号操作符来辅助赋值。在赋值时使用逗号操作符分割值,最终会返回表达式中最后一个值。

let num = (5, 1, 4, 8, 0); // num的值为0

这个例子中,num将被赋值为0,因为0是表达式中最后一项。逗号操作符的这种使用场景并不多见,但这种行为的确存在。

💬 欢迎评论!请确保您已登录 GitHub。

最近更新: 2025/6/28 02:51
Contributors: chenshicong, onion-chen
Prev
1.3数据类型
Next
1.5语句