操作符的问题,在严格的语法中不存在,但是在js中,因为其会按照需求自动转换数据类型,所以就出现了各种各样的问题,也可以说是小技巧,仅供参考。
下面的总结来自:图灵程序设计丛书"javascript高级程序设计"第三版。
一:一元操作符(++,--,+,-)
这四个操作符对任何值都适用,包括数字,字符串,布尔值,和对象,在应用于不同的值时,其遵循的规则如下:
1,在应用于一个包含有效数字字符的字符串(字符串中只能是数值类型的)时,先将其转换成数字值,在执行操作,字符串变量变成数值变量。(我们最习惯的用法)。
2,在应用于一个不包含有效数字字符的字符串时,麻将变量的值置为NaN。
3,在应用布尔值时,先将布尔值转换成数字,true=1,false=0,之后再执行操作,布尔值变量变成了数值变量。
4,在应用于对象时,先调用对象的valueof()方法已取得可供操作的值,再针对该值应用上面的三条规则。
例:
var s1 = "2";
var s2 = "z";
var s3 = false;
var s4 = 1.1;
var s5 = {valueOf:function(){
return -1;
}};
s1++; //3
s2++; //NaN
s3++; //1
s4--; //0.100000000000000009(由于浮点数的舍入误差,所以浮点数在用于比较条件时,要特别注意)
s5--; //-2
alert(s1+"--"+s2+"--"+s3+"--"+s4+"--"+s5);
var sw1 = "2";
var sw2 = "z";
var sw3 = false;
var sw4 = 1.1;
var sw5 = {valueOf:function(){
return -1;
}};
sw1 = -sw1; //-2
sw2 = -sw2; //NaN
sw3 = -sw3; //0
sw4 = +sw4; //1.1
sw5 = +sw5; //-1
alert(sw1+"**"+sw2+"**"+sw3+"**"+sw4+"**"+sw5);
二:位操作符
该操作中的特殊在于负数,负数的操作会以其补码进行,即一个负数会变转换成本身的补码,以补码进行之后的操作。
求补码:首先求这个数值绝对值的二进制,求这个二进制的反码(即0替换1,1替换0),得到的反码加1。
注意:有符号数,最高位是不允许操作的;Infinity和NaN在位操作时,会被当成0来处理。
1,按位非(NOT)(~) -- 结果就是返回数值的反码。
var num1 = 25;
var num2 = "z";
num1 = ~num1; //-26
num2 = ~num2; //-1
alert(num1+" "+num2);
var num3 = 25;
num3 = -num3 - 1;//-26 操作数的负值减1
alert(num3);
2,按位与(AND)(&)
3,按位或(OR)(|)
4,按位异或(XOR)(^)
5,左移(<<) -- 左移之后,右侧的空位以0填充。
6,有符号右移(>>)
最左侧的符号位不变,右移之后的空位会用符号位的值进行填充。
var num1 = 64;
var num2 = -64;
num1 = num1>>5; //2
num2 = num2>>5; //-2 //先转补码,右移操作,再转补码
alert(num1+" "+num2);
7,无符号右移(>>>)
会将数值的所有32位都向右移动,对于正数来说,无符号右移和有符号右移的结果一样。
但是对于负数来说,无符号右移是以0来填充空位,而不像是有符号右移那样以符号位的值来填充空位。
根本差距就是:负数的无符号右移就是,把负数转成补码操作完之后,不再进行补码转换,就结束了
var num1 = 64;
var num2 = -64;
num1 = num1>>5; //2
num2 = num2>>5; //134217726 //先转补码,右移操作,结束
alert(num1+" "+num2);
alert(num2.toString(2)); //111111111111111111111111110,再次对该二进制进行补码转换,就等于有符号的右移结果。
三:布尔操作符
1,逻辑非(!)
逻辑操作符首先会将它的操作数转换为一个布尔值,然后再求其反。
规则:
(1):如果操作数是一个对象,一个非空字符串,任意非0数值(包括Infinity)则返回false
(2):空字符串,数值0,null,NaN,undefined,返回true;
例:
var s1 = "2";
var s2 = "z";
var s3 = false;
var s4 = null;
var s5 = {valueOf:function(){
return false;
}};
alert(!s1+" "+!s2+" "+!s3+" "+!s4+" "+!s5);//false false true true false(不会按照返回值进行判断)
2,逻辑与(&&)
逻辑与属于短路操作,即如果第一个操作数可以决定结果(比如第一个操作数是false,则直接返回),那么不会进行第二个操作数的操作求值。
基本规则:
(1):如果第一个操作数是对象,则返回第二个对象;(因为对象布尔值为true);
(2):如果第二个操作数十对象,则只有在第一个操作数的求值结果是true时,才会返回第二个对象。(如果第一个对象为false,则结束,不会对第二个操作数进行求值)。
(3):如果有一个操作数是null,则返回null;
(4):如果有一个操作数是NaN,则返回NaN;
(5):如果有一个操作数是undefined,则返回undefined;
例:
var s1 = "2";
var s2 = "z";
var s3 = false;
var s4 = NaN;
var s5 = {valueOf:function(){
return false;
}};
alert(s2&&s1); //2
alert(s3&&s5); //false
alert(s5&&s4); //NaN
alert(s4&&s5); //NaN
3,逻辑或(||)
逻辑或也属于短路操作,即如果第一个操作数可以决定结果(比如第一个操作数是true,则直接返回),那么不会进行第二个操作数的操作求值。
基本规则:
(1):如果第一个操作数是对象,则返回第一个对象;(因为对象布尔值为true);
(2):如果第二个操作数十对象,则只有在第一个操作数的求值结果是false时,才会返回第二个对象。(如果第一个对象为true,则结束,不会对第二个操作数进行求值)。
(3):如果两个操作数都是对象,则返回第一个操作数。
(4):如果两个操作数是null,则返回null;
(5):如果两个操作数是NaN,则返回NaN;
(6):如果两个操作数是undefined,则返回undefined;
(7):如果操作数为false,null,NaN,undefined中的两种,则返回后面的,如果有非这四种的,则返回其他的操作数。
例:
var s1 = "2";
var s2 = "z";
var s3 = false;
var s4 = NaN;
var s5 = {valueOf:function(){
return false;
}};
var s6 = NaN;
alert(s2||s1); //z
alert(s3||s4); //NaN
alert(s5||s4); //对象
alert(s4||s5); //对象
四:乘性操作符
1,乘法(*)
规则:
(1):超出范围,则返回Infinity或者-Infinity
(2):如果有一个操作数是NaN,则返回NaN
(3):如果是Infinity与0相乘,则结果NaN
(4):如果Infinity与非0值相乘,则结果Infinity或者-Infinity
(5):如果Infinity与Infinity相乘,则结果Infinity
(6):如果操作数不是数值,则转换成数字值之后,再进行上面的操作。
2,除法(/)
规则:
(1):正常操作超出范围,返回Infinity或者-Infinity
(2):如果有一个操作数是NaN,则返回NaN
(3):如果Infinity除Infinity,则结果NaN
(4):如果0除0,则结果NaN
(5):如果非0数除以0,则结果为Infinity或者-Infinity
(6):如果有非数值,则转换成数值进行上述操作
3,求模(%)
规则:
(1):如果操作数都是数值,执行常规的除法计算,返回除得的余数
(2):如果被除数是无穷大而除数是有限大的数值,则结果是NaN
(3):如果被除数是有限大的数值而除数是0,则结果NaN
(4):如果是Infinity被Infinity除,则结果为NaN
(5):如果被除数是有限大的数值,而除数是无穷大的数值,则结果是被除数
(6):如果被除数是0,则结果是0
(7):如果有一个操作数不是数值,则在后台调用Number()将其转换为数值,然后执行上面的操
五:加性操作符
1,加法(+)
规则:
(1):如果有一个操作数是NaN,则结果为NaN
(2):如果是Infinity加Infinity,则结果为Infinity(负值的那个类似)
(3):如果是Infinity加-Infinity,则结果为NaN
(4):如果是+0加+0,则结果是+0
(5):+0加-0,则结果为+0
(6):-0加-0,则结果为-0(感觉这三个意义不大。还是对这些最基础的了解不深。。)
如果是字符串,
(7):把所有的操作数转成字符串,并把字符串连接起来
注意:只要在一个加法表达式中,有字符串,就会把字符串之后的操作数转成字符串,按照字符串进行操作。
例,2+3+"4" //结果为54
"4"+2+3 //结果为423
"4"+(2+3)//结果为45
2,减法(-)
规则:
(1):如果两个操作数都是数值,则执行常规的算术剑法操作并返回结果
(2):如果有一个操作数是NaN,则结果是NaN
(3):如果Infinity或-Infinity减Infinity或-Infinity,则结果是NaN
(4):如果Infinity或-Infinity减-Infinity或Infinity,则结果是Infinity或-Infinity
(5):+0减+0,则结果是+0
(6):+0减-0,则结果是-0
(7):-0减-0,则结果是+0
(8):如果有一个操作数是字符串,布尔型,null或者undefined,则现在后台调用Number()函数将其转换为数值,然后再根据前面的规则处理
(9):如果有一个操作数是对象,则调用对象的valueOf()方法以取得表示该对象的数值,如果对象没有valueOf方法,则调用toString()转换成字符串,再进行上述规则操作。
六:关系操作符
规则:
(1):如果两个操作数都是数值,则执行数值比较
(2):如果两个操作数都是字符串,则比较两个字符串对于的字符串编码值
(3):如果一个操作数是数值,则将另一个转换为数值,进行比较
(4):如果一个操作数是对象,则用valueOf()方法,比较,若无valueOf()方法,则调用toString()方法,再用之前的比较
(5):如果一个操作数是布尔值,则现将其转换为数值,然后再执行比较
(6):任何数与NaN比较,结果都为false
例:
var s1 = "23" < "3"; //true
var s2 = "23" < 3; //false
var s3 = "a" < 3; //false
var s4 = NaN == 3; //false
var s5 = NaN < 3; //false
var s6 = NaN > 3; //false
alert(s1+" "+s2+" "+s3+" "+s4+" "+s5+" "+s6);
var s4 = null == 0; //false
var s5 = null < 1; //true
var s6 = null > 0; //false
七:相等操作符
1,相等和不相等---先转换成匹配的类型再比较
(1):如果是布尔值,则在比较相等性之前,转换成数值
(2):如果一个操作数是字符串,另外一个是数值,则先把字符串转成数值,在比较
(3):如果一个操作数是对象,另外一个不是,则先把对象用valueOf()方法,用得到的基本类型值按照前面的规则比较
(4):null和undefined是相等的
(5):要比较相等性之前,不能将null和undefined转换成其他任何字符
(6):只要有一个操作数为NaN,则结果必定为false,因为NaN不等于NaN
(7):如果两个操作数都是对象,则比较它们是不是同一个对象,如果两个操作数都指向同一个对象,则为true
2,全等和不全等---不需要转换,直接比较
直接,完全一样才会返回true
八:条件操作符
九:赋值操作符
十:逗号操作符