阮一峰JS三轮复习——第二天

622 阅读6分钟

三、 运算符

3.1 算术运算符

3.1.1 加法运算符

加法运算符(+)是最常见的运算符,用来求两个数值的和。如果有字符串就变成字符串的拼接。

加法运算符是在运行时决定是执行相加还是连接,运算子的不同,导致了不同的语法行为,这种现象称为“重载”。

1.对象的相加

如果运算子是对象,必须先转为原始类型的值,然后再相加。

var obj = { p: 1 };
obj + 2 // "[object Object]2"

对象转为原始类型值规则如下:

  1. 自动调用对象的valueOf()方法,一般来说,对象的valueOf方法总是返回对象自身
  2. 然后再调用对象的toString()方法,对象的toString方法默认返**[object Object]**
  3. 这里有一个特例,如果运算子是一个Date对象的实例,那么会优先执行toString方法。
let date = new Date();
date.toString() // Mon Jul 12 2021 21:49:13 GMT+0800 (中国标准时间)

3.1.2 自增和自减运算符

它们是一元运算符,只需要一个运算子。自增和自减运算符有一个需要注意的地方,就是放在变量之后,会先返回变量操作前的值,再进行自增/自减操作,放在变量之前,会先进行自增/自减操作,再返回变量操作后的值。

var x = 1;
var y = 1;

x++ // 1
++y // 2

3.1.3 数值运算符(+)

数值运算符的作用在于将任何值转为数值,与Number函数的作用相同。

+true // 1
+[] // 0
+{} // NaN

3.2 比较运算符

比较运算符分为两类,相等比较和非相等比较。对于非相等比较,算法是先看两者是否都是字符串,如果是则照字典顺序比较,否则,将它们都转为数值,再进行比较。

1. 都是字符串的比较

'cat' > 'dog' // false
'cat' > 'catalog' // false

2. 非字符串的比较

2.1 原始类型值

如果两个运算子都是原始类型的值,则是先转成数值再比较。

5 > '4' // true
// 等同于 5 > Number('4')

true > false // true
// 等同于 Number(true) > Number(false)
// 即 1 > 0

这里需要注意与NaN的比较。任何值(包括NaN本身)与NaN使用非相等运算符进行比较,返回的都是false。

2.2 对象

如果运算子是对象,会转为原始类型的值,再进行比较。空数组返回一个空字符串。

[2] > [1] // true

[2] > [11] // true

{ x: 2 } >= { x: 1 } // true

3.3 布尔运算符

3.3.1 取反运算符(!)

取反运算符是一个感叹号,用于将布尔值变为相反值,对于非布尔值,取反运算符会将其转为布尔值。只有6个值为false(null undefined false 0 NaN ")

3.3.2 且运算符(&&)

且运算符(&&)往往用于多个表达式的求值。

它的运算规则是:如果第一个运算子的布尔值为true,则返回第二个运算子的值(注意是值,不是布尔值);如果第一个运算子的布尔值为false,则直接返回第一个运算子的值,且不再对第二个运算子求值。

't' && '' // ""
't' && 'f' // "f"
't' && (1 + 2) // 3
'' && 'f' // ""
'' && '' // ""

3.4 二进制位运算符

3.4.1 概述

二进制位运算符用于直接对二进制位进行计算,一共有7个。所有的位运算都只对整数有效。二进制否运算遇到小数时,也会将小数部分舍去,只保留整数部分。

  1. 二进制或运算符(or):符号为 | ,表示若两个二进制位都为0,则结果为0,否则为1。
  2. 二进制与运算符(and):符号为 & ,表示若两个二进制位都为1,则结果为1,否则为0。
  3. 二进制否运算符(not):符号为 ~ ,表示对一个二进制位取反。
  4. 异或运算符(xor):符号为 ^ ,表示若两个二进制位不相同,则结果为1,否则为0。、
  5. 左移运算符(left shift):符号为 << ,详见下文解释。
  6. 右移运算符(right shift):符号为 >> ,详见下文解释。
  7. 头部补零的右移运算符(zero filled right shift):符号为>>>,详见下文解释。

这些运算符直接处理每一个比特位,是非常底层的运算,好处是速度快,缺点是不够直观。在 JavaScript 内部,做位运算的时候,是以32位带符号的整数进行运算的,并且返回值也是一个32位带符号的整数。

3.4.2 二进制或运算符

0 | 3 // 3
相当于 00 | 11 =》 二进制11,也就是3 

位运算只对整数有效,遇到小数时,会将小数部分舍去,只保留整数部分。 所以,将一个小数与0进行二进制或运算,等同于对该数去除小数部分,即取整数位。

2.9 | 0 // 2
-2.9 | 0 // -2

3.4.3 二进制否运算符

二进制否运算符(~)将每个二进制位都变为相反值(0变为1,1变为0)

~ 3 // -4

取反运算比较复杂,简单记忆就是 一个数与自身的取反值相加等于 -1。

3.4.5 异或运算符

异或运算(^)在两个二进制位不同时返回1,相同时返回0。

“异或运算”有一个特殊运用,连续对两个数a和b进行三次异或运算,a^=b; b^=a; a^=b;,可以互换它们的值。这意味着,使用“异或运算”可以在不引入临时变量的前提下,互换两个变量的值。

var a = 10;
var b = 99;

a ^= b, b ^= a, a ^= b;

a // 99
b // 10

3.4.6 左移运算符

左移运算符(<<)表示将一个数的二进制值向左移动制定的位数,尾部补零,即乘以2的指定次方,

// 4 的二进制形式为100,
// 左移一位为1000(即十进制的8)
// 相当于乘以2的1次方
4 << 1
// 8

-4 << 1
// -8

3.4.7 右移运算符

右移运算符(>>)表示将一个数的二进制值向右移动指定的位数,右移运算符基本上相当于除以2的指定次方(最高位即符号位参与移动)。右移运算可以模拟 2 的整除运算。

4 >> 1 // 2
-4 >> 1 // -2
5 >> 1
// 2
// 相当于 5 / 2 = 2

21 >> 2
// 5
// 相当于 21 / 4 = 5

21 >> 3
// 2
// 相当于 21 / 8 = 2

21 >> 4
// 1
// 相当于 21 / 16 = 1

3.4.8 头部补零右移运算符

头部补零的右移运算符(>>>)与右移运算符(>>)只有一个差别,就是一个数的二进制形式向右移动时,头部一律补零,而不考虑符号位。

所以,该运算总是得到正值。对于正数,该运算的结果与右移运算符(>>)完全一致,区别主要在于负数。

3.5 其他运算符,运算顺序

3.5.1 void 运算符

void运算符的作用是执行一个表达式,然后不返回任何值,或者说返回undefined。

void 0 // undefined
void(0) // undefined

这个运算符的主要用途是浏览器的书签工具(Bookmarklet),以及在超级链接中插入代码防止网页跳转。

<a href="javascript: void(document.form.submit())">
  提交
</a>
用户点击链接提交表单,但是不产生页面跳转。