Javascript 高级编程 3章36页 【操作符】

219 阅读9分钟

操作符

包括:

  • 算术操作符
  • 位操作符
  • 关系操作符
  • 相等操作符 可以应用于:
  • 字符串
  • 数字值
  • 布尔值
  • 对象:要先调用valueOf()toString(),以获得可以操作的值

一元操作符:递增和递减操作符

  • 前置型
  • 后置型
//前置型:
var age = 29;
var anotherAge = --age + 2;

alert(age); //28
alert(anotherAge); //30
//前置型:
var age = 29;
++age;

//等同于:
var age = 29;
age = age + 1;

++age或age++单独成行的时候,两者是一样的

var num1 = 2;
var num2 = 20;
var num3 = num1-- + num2;   //22
var num4 = num1 + num2;  //21

++ 和 -- 可以用于任何数据类型,规则是先转换为数值类型,再进行++或--

  • 字符串
    • 包含有效数字,转为数字,再加减1
    • 不包含有效数字,转为NaN, 再加减1,还是NaN
  • 布尔值
    • false转为0, 再加减1
    • true转为0,再加减1
  • 对象
    • 先调用valueOf(),得到值
    • 如果得不到,则调用toString(),在用前面应用于字符串的规则
var s1 = "2";
s1++;   //3

var s2 = "z";
s2++;  //NaN

var b = false;
b++;  //1

var f = 1.1;
f--;  //0.100000000000009 (由浮点舍入错误所致)

var o = {
   valueOf: function() {
       return -1;
   }
};
o--;  //-2

一元操作符:一元加和减操作符

等同于数学书上讲的,正负号

  • 对于数值
    • 一元加,数值不变
    • 一元减,数值变为负的
  • 对于非数值
    • Number()一样先对这个非数值进行转换
    • 再按一元加或减,对应为正或者负
var s1 = "01";
s1 = +s1;  //变成数值1

位操作符

  • ECMAScript中所有数值,都以64位存储
  • 位操作符不直接操作64位的值,而是操作32位的值
  • 后台会自动完成64位转32位,位操作符运算,32位转64位
  • NaNInfinity,会被当成0
  • 对于非数值,会先自动Number()转换为数值
  • 有符号数
    • 正数,前31位是数值的二进制,第32位是0
    • 负数,前31位是数值的二进制补码,第32位是1
  • 无符号数,32位全表示数值,只能为正数
  • 二进制补码的计算方法:
    • 求数值绝对值的二进制码
    • 将二进制码做反码,0换为1,1换为0
    • 反码加1
  • 对于开发者,以下内容都是不可见的:
    • 64位
    • 二进制补码
//二进制补码,并不显示给开发者
var num = -18;
alert(num.toString(2));  //"-10010"

按位非 (~) NOT

  • 返回数值的反码,例如对25的按位非,是-26
var num1 = 25;
var num2 = ~num1;
alert(num2); //-26

按位与 (&) AND

  • 两个操作数先用二进制表示
  • 再按位对齐
  • 再按位 & (都为1时,才为1
var result = 25 & 3;
alert(result); //1

按位或 (|) OR

  • 两个操作数先用二进制表示
  • 再按位对齐
  • 再按位 | (只要有一个为1时,就为1
var result = 25 | 3;
alert(result); //27

按位异或 (^) XOR

  • 两个操作数先用二进制表示
  • 再按位对齐
  • 再按位 ^ (只有一个为1时,就为1
var result = 25 ^ 3;
alert(result); //26

左移 (<<)

  • 操作数先用二进制表示
  • 所有位向左移动指定位数
  • 空位用0填充
  • 不影响符号位
var oldValue = 2;   //二进制10
var newValue = oldValue << 5; //二进制1000000, 十进制64

有符号右移 (>>)

  • 操作数先用二进制表示
  • 所有位向右移动指定位数
  • 空位用符号位填充
  • 不影响符号位
var oldValue = 64;   //二进制1000000
var newValue = oldValue >> 5; //二进制10, 十进制2

无符号右移 (>>>)

  • 对于负数:
    • 操作数先用其绝对值的二进制补码表示
    • 所有位向右移动指定位数
    • 空位用0填充
  • 对于正数:
    • 操作数先用二进制表示
    • 所有位向右移动指定位数
    • 空位用0填充
var oldValue = -64;   
var newValue = oldValue >>> 5; //十进制134217726

布尔操作符

  • 逻辑非(NOT)
  • 逻辑与(AND)
  • 逻辑或(OR)

逻辑非 (!)

  • !表示
  • 可用于任何值
数据类型求逻辑非后的值
对象false
空字符串true
非空字符串false
0true
非0数值false
nulltrue
NaNtrue
undefinedtrue
//判非
alert(!false);   //true
alert(!"blue");  //false
alert(!0);       //true
alert(!NaN);     //true
alert(!"");      //true
alert(!12345);   //false

使用两个叹号!!,可以将数值转换为其所代表的布尔值

//转换为布尔值
alert(!!"blue");  //true
alert(!!0);       //false
alert(!!NaN);     //false
alert(!!"");      //false
alert(!!12345);   //true

逻辑与 (&&)

  • &&表示,有两个操作数
  • 可以用于任何类型
  • 短路操作
var found = true;
var result = (found && someUndefinedVariable);  //someUndefinedVariable没定义,因此发生错误
alert(result);   //这一行不会执行
var found = false;
var result = (found && someUndefinedVariable);  //短路,因此不会发生错误
alert(result);   //这一行会执行
  • 如果有一个操作数不是布尔值,结果就不一定返回布尔值
情况返回值
第一个操作数是对象第二个操作数
第二个操作数是对象,第一个操作数求值为true,则短路第二个操作数,即该对象
两个操作数是对象第二个操作数
第一个操作数是nullnull
第一个操作数是NaNNaN
第一个操作数是undefinedundefined

逻辑或 (||)

  • ||表示,有两个操作数
  • 可以用于任何类型
  • 短路操作
  • 如果有一个操作数不是布尔值,结果就不一定返回布尔值
情况返回值
第一个操作数是对象第一个操作数
第二个操作数是对象,第一个操作数求值为false,则短路第二个操作数
两个操作数是对象第一个操作数
第一个操作数是nullnull
第一个操作数是NaNNaN
第一个操作数是undefinedundefined

妙用:利用||来避免为变量赋nullundefined

//如果 perferredObject 的值:
//  不是null, 则 perferredObject 赋给 myObject
//    是null, 则 backupObject 赋给 myObject

var myObject  = perferredObject || backupObject;

乘性操作符

  • 包括:
    • 乘法
    • 除法
    • 求模
  • 操作数为非数值时,执行自动转换,转换为数值

乘法 (*)

var result = 34 * 56;
  • *表示两个数值的乘积
  • 规则如下:
情况结果
数值与数值 相乘常规乘法计算。只一个操作数有符号,则结果为负数。乘积超出ECMAScript数值范围,则返回Infinity或-Infinity
与NaN 相乘NaN
Infinity与0 相乘NaN
Infinity与非0数值 相乘Infinity或-Infinity,符号取决于非0数值的符号
Infinity与Infinity 相乘Infinity

除法 (/)

  • /表示
  • 规则如下:
情况结果
数值与数值常规除法计算。只一个操作数有符号,则结果为负数。商超出ECMAScript数值范围,则返回Infinity或-Infinity
与NaN 运算NaN
0被0 除NaN
非0有限数被0 除Infinity或-Infinity,符号取决于非0数值的符号
Infinity被Infinity 除NaN
Infinity被非0数值 除Infinity或-Infinity,符号取决于非0数值的符号

求模 (%)

var result = 26 % 5;  //等于1
  • %表示
  • 规则如下:
情况结果
数值与数值常规除法计算。返回余数
被除数是无穷大,除数是有限大NaN
被除数是有限大,除数是0NaN
被除数是Infinity,除数是InfinityNaN
被除数是有限大,除数是无穷大被除数
被除数是00

加性操作符

  • 加法
  • 减法

加法 (+)

  • +表示
  • 规则如下:
情况结果
一个操作数是NaNNaN
Infinity 加 InfinityInfinity
-Infinity 加 -Infinity-Infinity
Infinity 加 -InfinityNaN
+0 加 +0+0
-0 加 -0-0
+0 加 -0+0
两个操作数 都是 字符串拼接起来
一个操作数是 字符串,另一个操作数是 对象、数值或布尔值将另一个操作数tostring()转换成字符串,并拼接起来
一个操作数是字符串,另一个操作数是 undefinednull将另一个操作数String()转换成字符串"undefined"或"null",并拼接起来

减法 (-)

  • -表示
  • 规则如下:
情况结果
一个操作数是NaNNaN
Infinity 减 InfinityNaN
-Infinity 减 -InfinityNaN
Infinity 减 -InfinityInfinity
-Infinity 减 Infinity-Infinity
+0 减 +0+0
-0 减 +0-0
-0 减 -0+0
一个操作数是 字符串,布尔值,undefinednullNumber()转换成数值,再做减法计算。如果转换结果为NaN, 则为NaN
一个操作数是对象ValueOf()取得对象的数值。如果数值对象为NaN,则为NaN。如果对象没有ValueOf()方法,则调用其toString()方法,再将字符串转换为数值

关系操作符

  • 包括 <, >, <=, >=
  • 操作数有非数值时,需要进行数据转换或完成某些奇怪的操作:
情况结果
两个操作数,都是数值比较数值
两个操作数都是字符串比较对应的字符编码值 (大写字母的编码值全部小于小写字母)
一个操作数是数值另一个操作数转换为数值,比较数值
一个操作数是对象调用此对象的valueOf()得到数值,比较。如果对象没有valueOf()方法,调用toString得到字符串,比较。
一个操作数是布尔值转换成数值,比较
一个操作数是NaNfalse

相等操作符

  • 相等和不相等,操作符
  • 全等和不全等,操作符

相等 (==) 和 不相等 (!=)

  • 先转换操作数,然后再比较它们的相等性 (强制转型

  • 以下是转换规则: | 情况 | 结果 | | --- | --- | | 一个操作数是布尔值 | 将其转换为数值 | | 一个操作数是字符串,另一个操作数是数值 | 将字符串转换为数值 | | 一个操作数是对象,另一个操作数不是 | 调用valueOf(),将结果进行比较 |

  • 以下是相等性规则:

情况结果
null和undefined比较相等
一个操作数是null或undefined不将null和undefined转换成其他任何值
一个操作数是NaN==返回false,!=返回true
NaN和NaN比较==返回false,!=返回true
两个操作数都是对象如果都指向同一个对象,则返回true,否则,返回false

全等 (===) 和不全等(!==)

  • 不转换操作数, 其余和(==)及(!=)是一样的

推荐使用 全等 (===) 和不全等(!==)

条件操作符 (bool?a:b)

  • variable = boolean_expression ? true_value : false_value;
var max = (num1 > num2) ? num1 : num2;

赋值操作符 (=)

  • 复合赋值操作符:(=)前面加上乘性操作符,加性操作符,位操作符
    • *=
    • /=
    • %=
    • -=
    • <<=
    • >>=
    • >>>=
  • 复合赋操作符:简化操作,不提升性能

逗号操作符 (,)

  • 用于在一条语句中执行多个操作
  • 用于赋值时,总是返回表达式的最后一项
var num1 = 1, num2 = 2, num3 = 3;

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