一、一元操作符:只能操作一个值的操作符
1.递增(++)递减(--)操作符(前置递增递减、后置递增递减)
规则:
>应用于整数
>在应用于一个包含有效数字字符的字符串时,先将其转换为数字值,再执行加减1的操作。字符串变量变成数值变量。
>在应用与一个不包含有效数字字符的字符串时,将变量的值设置为NaN,字符串变量变成数值变量
>在应用于布尔值false时,先将其转换为0再执行加减1的操作,布尔值变量变成数值变量
>在应用于布尔值true时,先将其转换为1再执行加减1的操作,布尔值变量变成数值变量
>在应用与浮点数值时,执行加减1的操作
>在应用于对象时,先调用对象的valueOf()以取得一个可供操作的值。然后对改值应用前述规则。如果结果是NaN,则在调用toString()后再应用前述规则。对象变量变成数值变量。
例子:
var s1 = "2";
console.log(s1++); //3
var s2 = "z";
console.log(s2++); //NaN
var f = 1.1;
console.log(f--); //0.10000000000000009(由于浮点舍入错误所致)
var o = {
valueOf:function(){
return -1;
}
};
console.log(o--); //-2
2.一元加和减操作符(+、-)---主要用于基本算术运算,也可以像前面示例展示的一样用于转换数据类型。
规则:
>一元加放在数值前面,对数值不会产生任何影响,一元减会使该值变为负数
>在对非数值应用一元加操作符时,会像Number()转型函数一样对这个值进行转换。应用一元减操作符遵循与一元加操作符相同规则,最后将得到的数值转换为负数。
例子:
var s1 = "01";
s1 = +s1;
console.log(s1); //1
var s2 = "1.1";
s2 = +s2;
console.log(s2); //1.1
var o = {
valueOf:function(){
return -1;
}
};
o = -o;
console.log(o); //1
二、位操作符
PS:当对数值应用位操作符时,后台会将64位的数值转换成32位数值,然后执行位操作,最后再将32位的结果转换回64位数值。这样,表面上看起来就好像是在操作32位数值,但这个转换过程也导致了一个严重的副效应,即在对特殊的NaN和Infinity值应用位操作时,这两个值都会被当做0来处理。
如果对非数值应用位操作符,会先使用Number()函数将该值转换为一个数值(自动完成),然后再应用位操作符。得到的结果将是一个数值。
1.按位非(~)---返回数值的反码,本质即操作数的负值减1(ES中少数几个与二进制计算有关的操作符之一)
例子:
var num = 25;
var num2 = -num;
console.log(num2); //-26
虽然-num -1也能返回同样的结果,但由于按位非是在数值表示的最底层执行操作,因此速度更快。
2.按位与(&)---只在2个数值的对应位都是1时才返回1,任何一位是0,结果都是0。
例子:
var result = 25 & 3;
console.log(result); //1 ( 11001 & 0011 》 1 》1)
3.按位或(|)---在有一个位是1的情况下就返回1,而只有在2个位都是0的情况下才返回0)
例子:
var result = 25|3;
console.log(result); //27( 11001 | 00011 》11011 》27)
4.按位异或(^)---在2个数值对应位上只有一个1时才返回1,如果对应位的2位都是1或都是0,则返回0。
例子:
var result = 25 ^ 3;
console.log(result); //26( 11001 ^ 00011 》 11010 》26)
5.左移(<<)---这个操作符会将数值的所有位向左移动指定的位数。(不会影响操作数的符号位)
例子:
var oldValue = 2; //等于二进制的10
var newValue = oldValue <<5; 等于二进制的1000000,十进制的64
PS:在向左移位后,原数值的右侧多出了5个空位。左操作符会以0来填充这些空位,以便得到的结果是一个完整的32位二进制数。
6.有符号的右移(>>)---这个操作数会将数值向右移动,但保留符号位(即正负号标记)。
例子:
var oldValue = 64; //等于二进制的1000000
var newValue = oldValue >> 5; //等于二进制的10,即十进制的2
PS:这次的空位出现在原数值的左侧、符号位的右侧,而此时ES会用符号位的值来填充所有空位,以便得到一个完整的值。
7.无符号右移(>>>)---这个操作符会将数值的所有32位都向右移动,对正数来说,无符号右移的结果与有符号右移相同。
例子:
var oldValue = 64; //等于二进制的1000000
var newValue = oldValue >>> 5; //等于二进制的10,即十进制的2
但是对负数来说,情况就不一样了。首先,无符号右移是以0来填充空位,而不是像有符号右移那样以符号位的值来填充空位。所以,对整数的无符号右移与有符号右移结果相同,但对负数的结果就不一样了。其次,无符号右移操作符会把负数的二进制码当成正数的二进制码。而负数以其绝对值的二进制补码形式表示,因此就会导致无符号右移后的结果非常大。
例子:
var oldValue = -64; //等于二进制的11111111111111111111111111000000
var newValue = oldValue >>> 5; //等于二进制的00000111111111111111111111111110,等于十进制的134217726
三、布尔操作符
1.逻辑非(!)---首先会将它的操作数转换为一个布尔值,然后再对其求反。(同时使用2个逻辑非操作符,实际上就会模拟Boolean()转型函数的行为)
规则:
>如果操作数是一个对象,返回false
>如果操作数是一个空字符串,返回true
>如果操作数是一个非空字符串,返回false
>如果操作数是数值0,返回true
>如果操作数是任意非0数值(包括Infinity),返回false
>如果操作数是null,返回true
>如果操作数是NaN,返回true
>如果操作数是undefined,返回true
例子:
console.log(!false); //true
console.log(!"blue"); //false
console.log(!!NaN); //false
2.逻辑与(&&)---又称短路与,即如果第一个操作数就能够决定结果,那么就不会再对第二个操作数求值。
规则:
在有一个操作数不是布尔值的情况下,逻辑与操作就不一定返回布尔值。
>如果第一个操作数是对象,则返回第2个操作数
>如果第2个操作数是对象,则只有在第一个操作数的求值结果为true的情况下才会返回该对象
>如果2个操作数都是对象,则返回第2个操作数
>如果第一个操作数是null,则返回null
>如果第一个操作数是NaN,则返回NaN
>如果第一个操作数是undefined,则返回undefined
PS:不能在逻辑与操作中使用未定义的值,但如果第一个值为false,就不会发生错误了(不会再对第2个值求值了)
3.逻辑或(||)---短路或,如果第一个操作数的就只结果为true,就不会对第2个操作数求值了
规则:
与逻辑与相似,如果有一个操作数不是布尔值,逻辑或也不一定返回布尔值
>如果第一个操作数是对象,则返回第一个操作数
>如果第一个操作数的求值结果为false,则返回第二个操作数
>如果2个操作数都是对象,则返回第一个操作数
>如果2个操作数都是null,则返回null
>如果2个操作数都是NaN,则返回NaN
>如果2个操作数都是undefined,则返回undefined
PS:同样不能在逻辑或操作中使用未定义的值,但如果第一个值为true,就不会发生错误了(不会再对第2个值求值了)
我们可以利用逻辑或这一行为来避免为变量赋null或undefined值。
例如:
var myObject = preferredObject || backupObject;
解析:变量myObject将被赋予等号后面2个值中的一个。变量preferredObject中包含优先赋给myObject的值,变量backupObject负责在preferredObject中不包含有效值的情况下提供后备值。如果prederredObject的值不是null,那么它的值将被赋给myObject;如果是null,则将backupObject的值赋给myObject。ES程序的赋值语句经常会使用这种模式。
四、乘性操作符
1.乘法(*),用于计算2个数值的乘积。
在处理特殊值的情况下,遵循下列特殊规则:
>如果操作数都是数值,执行常规的乘法计算,即2个正数或2个负数相乘的结果还是正数,而如果只有一个操作数有符号,那么结果就是负数。如果乘积超过了ES数值的表示范围,则返回Infinity或 - Infinity
>如果有一个操作数是NaN,则结果是NaN
>如果是Infinity与0相乘,则结果是NaN
>如果是Infinity与非0数值相乘,则结果是Infinity或 -Infinity,取决于有符号操作数的符号
>如果是Infinity与Infinity相乘,则结果是Infinity
>如果有一个操作数不是数值,则在后台调用Number()将其转换为数值,然后再应用上面的规则
例子:
2.除法(/)---执行第2个操作数除第一个操作数的计算console.log(5 * "5"); //25 console.log(5 * null); //0 console.log(5 * "a"); //NaN console.log(5 * undefined); //NaN console.log(5 * NaN); //NaN console.log(5 * 5); //25 console.log(Infinity * 0); //NaN console.log(Infinity * 2); //Infinity console.log(Infinity * Infinity); //Infinity
与乘法操作符类似,除法操作符对特殊的值也有特殊的处理
规则:
>如果操作数都是数值,执行常规的除法计算,即2个正数或2个负数相除的结果还是正数,而如果只有一个操作数有符号,那么结果就是负数。如果商超过了ES数值的表示范围,则返回Infinity或 - Infinity
>如果有一个操作数是NaN,则结果是NaN
>如果是Infinity被Infinity除,则结果是NaN
>如果是0被0除,则结果是NaN
>如果是非零的有限数被零除,则结果是Infinity 或 -Infinity,取决与有符号操作数的符号
>如果是Infinity被任何非零数值除,则结果是Infinity或-Infinity,取决与有符号操作数的符号
>如果有一个操作数不是数值,则在后台调用Number()将其转换为数值,然后再应用上面的规则
例子:
console.log(5 / "5"); //1 console.log(5 / null); //Infinity console.log(5 / "a"); //NaN console.log(5 / undefined); //NaN console.log(5 / NaN); //NaN console.log(5 / 5); //1 console.log(0 / -5); //0 console.log(0 / 0); //NaN console.log(-5 / 0); //-Infinity console.log(null / 5); //0
3.求模(%)
与另外2个乘性操作符类似,求模操作符会遵循下列特殊规则来处理特殊的值
规则:
>如果操作数都是数值,执行常规的除法计算,返回除得的余数
>如果被除数是无穷大值而除数是有限大的数值,则结果是NaN
>如果被除数是有限大的数值而除数是零,则结果是NaN
>如果是Infinity被Infinity除,则结果是NaN
>如果被除数是有限大的数值而除数是无穷大的数值,则结果是被除数
>如果被除数是零,则结果是零
>如果有一个操作数不是数值,则在后台调用Number()将其转换为数值,然后再应用上面的规则
console.log(16 % "5"); //1 console.log(5 % null); //NaN console.log(5 % "a"); //NaN console.log(5 % undefined); //NaN console.log(5 % NaN); //NaN console.log(5 % 5); //0 console.log(5 % Infinity); //5 console.log(0 % 0); //NaN console.log(Infinity % Infinity); //NaN console.log(null % 5); //0 console.log(Infinity % 5); //NaN五、加性操作符(与乘法操作符类似,也会在后台转换不同的数据类型)
1.加法(+)
如果2个操作数都是数值,执行常规的加法计算:
>如果有一个操作数是NaN,则结果是NaN
>如果是Infinity + Infinity ,则结果是Infinity
>如果是-Infinity + (-Infinity),则结果是-Infinity
>如果是Infinity +(-Infinity),则结果是NaN
>如果是+0 + (+0),则结果是+0
>如果是-0 +(-0),则结果是-0
>如果是+0 +(-0),则结果是+0
不过如果有一个操作数是字符串,那么就要应用如下规则:
>如果2个操作数都是字符串,则将第二个操作数与第一个操作数拼接起来
>如果只有一个操作数是字符串,则将另一个操作数转换为字符串,然后再将2个字符串拼接起来
>如果另外有一个操作数是对象、数值或布尔值,则调用他们的toString()取得相应的字符串值,然后再应用前面关于字符串的规则。对与undefined和null,则分别调用String()函数并取得字符串"undefined"和"null"
如果一个数字加null或者undefined等非字符串,那么还是把null或者undefined进行Number()之后再相加
console.log(16 + "5"); //"165" console.log(5 + "a"); //"5a" console.log(5 + NaN); //NaN console.log(5 + null); //5 console.log("5" + null); //"5null" console.log(5 + undefined); //NaN console.log(null + undefined); //NaN console.log(5 + 5); //10 console.log("两个数的和是"+5+5); //"两个数的和是55" console.log("两个数的和是"+(5+5)); //"两个数的和是10"
2.减法(-)
在处理各种数据类型转换时,同样需要遵循一些特殊规则:
>如果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()并将得到的字符串转为数值。
>一个数字减Infinity,结果是-Infinity
例子:
console.log(16 - "5"); //11 console.log(5 - 5); //0 console.log(5 - "a"); //NaN console.log(5 - NaN); //NaN console.log(5 - null); //5 console.log(Infinity - Infinity); //NaN console.log(5 - undefined); //NaN console.log(5 - true); //4 console.log(5 - "true"); //NaN console.log(5 - ""); //5 console.log(5 - Infinity); //-Infinity console.log("两个数的差是"+5-5); //NaN console.log("两个数的差是"+(5-5)); //"两个数的差是0"
六、关系操作符
1.小于(<)、大于(>)、小于等于(<=)、大于等于(>=)这几个操作符用于对2个值进行比,返回一个布尔值
与ES中的其他操作符一样,当关系操作符的操作数使用了非数值时,也要进行数据转换或完成某些奇怪的操作
规则:
>如果2个操作数都是数值,则执行数值比较
>如果2个操作数都是字符串,则比较2个字符串对应的字符串编码值(大写的字符编码全部小于小写的,要和字母表中的位置大小一样,就必须把2个操作数转为相同的大小写)
>如果一个操作数是数值,则将另一个操作数转换为一个数值,然后执行数值比较
>如果一个操作数是对象,则调用这个对象的valueOf(),用得到的结果按照前面的规则执行比较。如果对象没有valueOf(),则调用toString(),并用得到的结果根据前面的规则执行比较
>如果一个操作数是布尔值,则先将其转换为数值,然后再执行比较
>任何操作数与NaN进行比较,结果都是false
console.log(16 > "5"); //true console.log("23">"3"); //false,2的字符编码是50,而3的字符编码是51 console.log(5 < "a"); //false,"a"被转换成了NaN console.log(5 >= NaN); //false console.log(NaN >= NaN); //false console.log(5 >= null ); //true console.log(5 >= undefined); //false console.log(5 >= 5); //true console.log(5 >= "true"); //false console.log(5 >= true); //true console.log(5 >= ""); //true console.log("Brick" > "al"); //false,B的字符编码值66,a为97 console.log("brick" > "al"); //true,小写字母b的编码值比a大
七、相等操作符
"=="、“!=”相等和不相等,先转换再比较(强制转换)(注意:null == undefined,他们是类似的值)
"==="、“!==”全等和不全等,仅比较而不转换(注意:null !==undefined,他们是不同类型的值)
在转换不同的数据类型时规则:
>如果有一个操作数是布尔值,则在比较相等性之前先将其转换为数值——false转为0,true转为1
>如果一个操作数是字符串,另一个操作数是数值,在比较相等性之前先将字符串转换为数值
>如果一个操作数是对象,另一个操作数不是,则调用对象的valueOf(),用得到的基本类型值按照前面的规则进行比较
这2个操作符在进行比较时要遵循下列规则:
>null和undefined是相等的
>要比较相等性之前,不能将null和undefined转换成其他任何值
>如果有一个操作数是NaN,则相等操作符返回false,而不相等操作符返回true。即使2个操作数都是NaN,相等操作符也返回false
>如果2个操作数都是对象,则比较他们是不是同一个对象。如果2个操作数都指向同一个对象,则返回true,否则返回false
例子:
console.log(true == 2); //false console.log(undefined == 0); //false console.log(null == 0); //false console.log(NaN != NaN); //true console.log("5" == 5); //true console.log(undefined == null ); //true console.log("NaN" == NaN); //false console.log(5 == NaN); //false console.log(false == 0); //true
八、条件操作符
三目表达式:variable = boolean_expersion ? true_value : false_value;
基于对boolean_expersion求值的结果,决定给变量variable赋什么值。如果求值结果为true,则给变量variable赋true_value,如果求值结果为false,则给变量variable赋false_value值。
例子:
var max = (num1 > num2) ? num1 : num2;
九、赋值操作符
· 简单的赋值操作符:如var num = 10; 其作用就是把右侧的值赋给左侧的变量
· 复合赋值操作符:设计这些操作符的主要目的就是简化赋值操作,使用他们不会带来任何性能的提示
>乘/赋值(*=)
>除/赋值(/=)
>模/赋值(%=)
>加/赋值(+=)
>减/赋值(-=)
>左移/赋值(<<=)
>有符号右移/赋值(>>=)
>无符号右移/赋值(>>>=)
九、逗号操作符
· 多用于声明多个变量,如var num1 = 1, num2 = 2, num3 = 3;
· 还可以用于赋值,在用于赋值时,逗号操作符总会返回表达式中的最后一项,如:var num =(5,1,4,8,0);//num的值为0