JavaScript基本概念——操作符

Get busy living,or get busy dying.

JavaScript操作符

ECMAScript 操作符与众不同之处在于,它能适用于对象,此时操作符通常会调用对象的 valueOf() 或 toString() 方法以取得可以操作的值。

一元操作符

只能操作一个值的操作符叫一元操作符。

1. 递增和递减操作符

借鉴自 C 语言,前置型会在语句运行时被执行,后置型会在语句结束后执行。
在应用于不同的值时,递增递减操作符遵循以下规则:

  • 应用于包含有效数字的字符串,先转换为数字,再执行加减操作,字符串变量变成数值变量
  • 应用于不包含有效数字的字符串,将变量的值设置为 NaN,字符串变量变成数值变量(NaN 是特殊的数值类型)
  • 应用于布尔值,先转换为数字 0 或 1,再执行加减操作,布尔值变量变成数值变量
  • 应用于浮点数值,执行加减操作
  • 应用于对象,先调用对象的 valueOf() 方法取得可操作的值,然后应用上述规则,若结果为 NaN,则调用 toString() 方法之后应用上述规则,对象变量变成数值变量

2. 一元加减操作符

一元加操作符置于非数字值之前时(置于之后会被认为是一个二元操作符),该操作符会像转型函数 Number() 一样对这个值执行转换。
一元减操作符主要用于表示负数,应用于非数字值时与一元加操作符类似。


位操作符

ECMAScript 中的所有数值都以 IEEE-754 64 位格式存储。位操作符不直接操作 64 位值,而是先将 64 位的值转换为 32 位的整数,然后执行操作,最后将结果转回 64 位。因此在实际操作过程中只存在 32 位整数。
对于有符号的整数,32 位中的前 31 位用于表示整数的值,第32位用于表示数值(符号位),0 表示正数,1 表示负数。
正负数都以二进制码存储,其中负数以其绝对值的二进制补码格式存储,计算补码的步骤如下:

  1. 求这个数值绝对值的二进制码
  2. 对二进制值求反码(0 换成 1,1 换成 0)
  3. 得到的反码加1

注意处理负数时,符号位是不能访问的。
把一个负数转换为二进制字符串,结果并不会显示补码,例如 (-6).toString(2) 的结果为"-0110",显然这种形式更符合逻辑。
默认情况下,ECMAScript 中所有整数都是有符号数。无符号数可以表示的值更大,因为多出一位来表示数值,但它不能表示负数。

在 ECMAScript 中,对数值应用位操作符时,后台自动将 64 位值转换为 32 位值,然后执行位操作,最后转回 64 位值。这会导致一个严重的问题:对 NaN 和 Infinity 值应用位操作符,它们会被当作 0 来处理。
在 ECMAScript 中,对非数值应用位操作符时,会先使用 Number() 函数转换为数值,再执行位操作,得到的结果是一个数值。

1. 按位非(NOT)

由一个波浪线(~)表示,执行结果是该数值的反码(负数以其绝对值的二进制补码格式存储,补码 = 反码 + 1)。
对5(二进制:101)求反码,结果为 -6(二进制:1111 1111 1111 1111 1111 1111 1111 1010);
对-5(二进制:1111 1111 1111 1111 1111 1111 1111 1011)求反码,结果为 4(二进制:100)。
可知按位非的本质就是:操作数的负值减 1。虽然通过算术式(-a-1)能得到相同结果,但是按位非的速度更快。

2. 按位与(AND)

由一个与字符(&)表示,它将两个数值按位对齐,只有两个对应位都是 1 时才返回1,否则返回 0。例如求 25 & 3 :

25:    0000 0000 0000 0000 0000 0000 0001 1001  
3:     0000 0000 0000 0000 0000 0000 0000 0011  
&:     0000 0000 0000 0000 0000 0000 0000 0001

3. 按位或(OR)

由一个竖线(|)表示,它将两个数值按位对齐,只有两个对应位都是 0 时才返回 0,否则返回 1。例如求 25 | 3:

25:    0000 0000 0000 0000 0000 0000 0001 1001  
3:     0000 0000 0000 0000 0000 0000 0000 0011  
|:     0000 0000 0000 0000 0000 0000 0001 1011

4. 按位异或(XOR)

由一个插入符(^)表示,它将两个数值按位对齐,只有两个对应位值不同时才返回1,否则返回 0。例如求 25 ^ 3:

25:    0000 0000 0000 0000 0000 0000 0001 1001  
3:     0000 0000 0000 0000 0000 0000 0000 0011  
^:     0000 0000 0000 0000 0000 0000 0001 1010

5. 左移

由两个小于号(<<)表示,它将数值所有位向左移动指定位数,低位补零。例如求 2 << 5:

2:     0000 0000 0000 0000 0000 0000 0000 0010  
64:    0000 0000 0000 0000 0000 0000 0100 0000

通常,左移不会影响符号位,左移 n 位相当于乘以 2 的 n 次方。但如果左移位数过多,可能会覆盖符号位,使得符号位改变或者丢失高位的问题,例如 2 << 30 的结果是 -2147483648,2 << 31 的结果是 0。

6. 右移

分为有符号右移(或算术右移)和无符号右移(或逻辑右移)。

  • 有符号右移
    由两个大于号(>>)表示,它将数值所有位向右移动指定位数,符号位为1则高位补 1,否则补 0。
  • 无符号右移
    由3个大于号(>>>)表示,它将数值所有位向右移动指定位数,不考虑符号位,高位补 0。
    由于负数是以其绝对值的二进制补码的格式表示,所以负数的无符号右移的结果会非常大。

布尔操作符

1. 逻辑非

由一个叹号(!)表示,可以应用于 ECMAScript 中的任何值,返回一个布尔值。逻辑非操作符会将操作的值转换为一个布尔值,取反并返回。转换规则如下:

  • 对象,返回 false
  • 空字符串,返回 true
  • 非空字符串,返回 false
  • 数值 0,返回 true
  • 数值 NaN,返回 true
  • 非 0 非 NaN 数值(包括 Infinity),返回 false
  • null,返回 true
  • undefined,返回 true
    同时使用两个逻辑非操作符,可以将一个值转换为与其对应的布尔值,与 Boolean() 转型函数的结果相同。

2. 逻辑与

由两个和号(&&)表示,可以应用于 ECMAScript 中的任何值。JavaScript 首先将 && 两边的值转成 Boolean 类型,然后再算结果,返回 true 时取后面的值,否则取前面的值。
数值转换为 Boolean类型 遵循以下规则:

  • 操作数为 false、null、undefined、0和NaN、'',则返回 false
  • 操作数为其他,则返回 true
    逻辑与是短路操作,第一个数值得 false 就会直接返回第一个值,不再计算第二个。

3. 逻辑或

由两个竖线符号(||)表示,可以应用于 ECMAScript 中的任何值。JavaScript 首先将||两边的值转成 Boolean 类型,然后再算结果,返回 true 时取前面的值,否则取后面的值。
逻辑或也是短路操作,第一个数值得 true 就会直接返回第一个值。


乘性操作符

ECMAScript 定义了 3 个乘性操作符:乘法、除法、求模。
如果参与乘性计算的某个操作数不是数值,操作符会自动使用 Number() 转型函数执行类型转换。

1. 乘法

由一个星号(*)表示,处理特殊值的情况下,乘法操作符遵循下列规则:

  • 如果有一个操作数是 NaN,则结果为 NaN
  • Infinity 与 Infinity 相乘,则结果是 Infinity
  • Infinity 与 0 相乘,则结果是 NaN
  • Infinity 与非 0 数值相乘,则结果是 Infinity 或 -Infinity
  • 如果有操作数不是数值,则调用 Number() 转换为数值,再应用上面的规则

2. 除法

由一个斜线号(/)表示,处理特殊值的情况下,除法操作符遵循下列规则:

  • 如果有一个操作数是 NaN,则结果为 NaN
  • Infinity 被 Infinity 除,则结果是 NaN
  • Infinity 被 0 除,则结果是 Infinity
  • Infinity 被非 0 有限数除,则结果是 Infinity 或 -Infinity
  • 非 0 有限数被 Infinity 除,则结果是 0
  • 非 0 有限数被 0 除,则结果是 Infinity 或 -Infinity
  • 0 被 Infinity 除,则结果是 0
  • 0 被 0 除,则结果是 NaN
  • 如果有操作数不是数值,则调用 Number() 转换为数值,再应用上面的规则

3. 求模

由一个百分号(%)表示,处理特殊值的情况下,求模操作符遵循下列规则:

  • 如果有一个操作数是 NaN,则结果为 NaN
  • Infinity 对任意数取模,则结果是 NaN
  • 任意数对 0 求模,则结果是 NaN
  • 有限数(包括 0)对 Infinity 求模,则结果是该有限数本身
  • 如果有操作数不是数值,则调用 Number() 转换为数值,再应用上面的规则

加性操作符

1. 加法

由一个加号(+)表示,处理特殊值的情况下,加法操作符遵循下列规则:

  • 如果两个操作数都是字符串,则将其拼接起来
  • 如果只有一个操作数是字符串,则调用另一个操作数的相应方法(对象,数值和布尔值调用其 toString() 方法,undefined 和 null 调用 String() 方法)取得其字符串,然后拼接起来
  • 如果有一个操作数是 NaN,且另一个操作数不是字符串,则结果为 NaN
  • Infinity 加 Infinity,则结果是 Infinity
  • -Infinity 加 -Infinity,则结果是 -Infinity
  • Infinity 加 -Infinity,则结果是 NaN
  • -0 加 -0,则结果是 -0
  • 0 加 -0 或者 -0 加 0,则结果是 0
  • 如果有一个操作数是对象,则调用其 toString() 方法取得对应的字符串,然后拼接起来;如果该对象的 prototype 链中都没有实现自己的 toString() 的话,就会调用 Object.prototype.toString.call(该对象) 获取对应字符串,例如两个空白对象相加的结果是"[object Object][object Object]"(这里第一个 object 表示其数据类型,与 typeof() 功能一样,第二个 Object 表示其构造方法)
  • 如果有一个操作数是布尔值,undefined 或 null,则调用 Number() 方法取得对应的数值,然后相加

2. 减法

由一个减号(-)表示,处理特殊值的情况下,减法操作符遵循下列规则:

  • 如果有一个操作数是 NaN,另一个操作数不是字符串,则结果为 NaN
  • Infinity 减 Infinity,则结果是 NaN
  • -Infinity 减 -Infinity,则结果是 NaN
  • Infinity 减 -Infinity,则结果是 Infinity
  • -Infinity 减 Infinity,则结果是 -Infinity
  • 0 减 0,则结果是 0
  • 0 减 -0,则结果是 0
  • -0 减 0,则结果是 -0
  • -0 减 -0,则结果是 0
  • 如果有一个操作数是字符串、布尔值、undefined 或 null,则调用 Number() 函数将其转换为数值
  • 如果有一个操作数是对象,则调用其 valueOf() 方法以获取该对象的数值,如果没有 valueOf() 方法则调用其 toString() 方法,并将得到的字符串通过 Number 转换为数值

关系操作符

由小于(<)、大于(>)、小于等于(<=)和大于等于(>=)组成,处理特殊值的情况下,关系操作符遵循下列规则:

  • 如果两个操作数都是字符串,则比较两个字符串对应的字符编码值(从第一个字符开始比较,如果相同则比较下一个,可以通过调用该字符串的 charCodeAt() 方法获取其编码值)
  • 如果有一个操作数是数值,则将另一个操作数转换为数值(转换失败时直接返回 NaN,任何值与NaN比较结果都为 false),然后进行比较
  • 如果有一个操作数是对象,则调用其 valueOf() 方法以获取对应值,再按照前面的规则进行比较,如果没有 valueOf() 方法则调用其 toString() 方法
  • 如果有一个操作数是布尔值,则先将其转换为数值,然后进行比较

相等操作符

ECMAScript 提供两组操作符:相等与不相等(先转换为相似类型再比较),和全等与不全等(仅比较不进行转换)

1. 相等和不相等

相等操作符由两个等于号(==)表示,不相等操作符由(!=)表示,比较前都会先转换操作数(强制转换),转化时遵循下列基本规则:

  • null 或 undefined 不会被转换,直接进行比较
  • 布尔值被转换为数值(true 为 1,false 为 0),然后进行比较
  • 如果有一个操作数是字符串,另一个是数值,则先将字符串转换为数值,再进行比较
  • 如果有一个操作数是对象,而另一个不是对象,则调用对象的valueOf()方法,用得到的值进行比较
    比较时遵循下列规则:
  • null 和 undefined 相等(它们也与自身相等,除此之外不与其他值相等)
  • 如果有一个操作数是 NaN,则判断其不相等(两个操作数都是 NaN 结果也是不相等,因为 NaN 不等于 NaN)
  • 如果两个操作数都是对象,则比较它们是否为同一个对象

2. 全等和不全等

全等操作符由 3 个等于号(===)表示,不全等操作符由(!==)表示,全等没有转换步骤,直接进行比较
null 和 undefined 不全等
为了保持代码中数据类型完整性,推荐使用全等操作符


条件操作符

遵循与 Java 中条件操作符相同的语法形式:
条件 ? 返回值1 : 返回值2
条件的结果为 true 则得到返回值 1,否则得到返回值 2


赋值操作符

由等号表示,作用就是把右侧的值赋给左侧的值
在等号前面加上其他算术操作符,可以组成复合赋值操作符:
a *= b 相当于 a = a * b
/=、%=、+=、-= 与之类似

  • 左移赋值:<<=(相当于乘以 2 的n次方,注意 JavaScript 的数字是 64 位有符号数,左移可能改变符号位)
  • 右移赋值:>>=(相当于除以 2 的 n 次方,左边补上符号位)
  • 无符号右移赋值:>>>= (左边始终补 0)
    复合运算符不会带来性能上的提升

逗号操作符

用于在一条语句中执行多个操作,声明多个变量。
此外还可用于赋值,如:
var a = (1,2,3); //此时逗号操作符只会返回最后一项

猜你喜欢

转载自www.cnblogs.com/zhangjun2013551829/p/9450489.html