操作符
定义:操作符能用于操作数据值,包括算术运算符、位操作符、关系操作符和相等操作符。操作符能适用于很多值,例如字符串、数字值、布尔值,甚至对象。在应用于对象时,相应的操作符通常会调用对象的valueOf()和(或)toString()方法,以便取得可以操作的值。
递增和递减操作符
(+ +,- -)应用于数值时,和java中没有区别。要注意的是操作符的位置分为前置和后置。前置递增使变量的值在语句被求以前改变(可以理解成返回递增后的值)。举个例子:
var age = 29 ;
var anotherage = ++age + 1 ;
所以最终得到了31 。这种在科学领域称为副效应。
var anotherage = age++ + 1 ;
var anotherage = age++ + age + 1 ;
var anotherage = ++age + age + 1 ;
var anotherage = age + ++age + 1 ;
当递增递减操作符应用于字符串、布尔值或者对象时。可以理解成在上一篇文章中提到过的,先将变量通过Number()函数转换为数值,再进行计算。这里就简单举3个object的例子:
var o1 = {
valueOf : function () {
return "1" ;
},
toString : function () {
return "2" ;
}
}
var o2 = {
toString : function () {
return "2" ;
}
}
var o3 = {
valueOf : function () {
return "1xx" ;
},
toString : function () {
return "2" ;
}
}
var o4 = {
valueOf : function () {
return "1xx" ;
},
toString : function () {
return "2xx" ;
}
}
alert(++o1);
alert(++o2);
alert(++o3);
alert(++o4);
o1和o2的结果是在预想中的,在执行自增运算时,先是求Number(o1),由于o1是对象,故先调用valueOf()方法再得到有效值”1”后,再执行Number(“1”)返回数值1自增得到2。o2的结果是因为没有重写valueOf方法,或者说valueOf方法的返回值执行Number后是NaN,所以再调用toString()最终得到3。o4的执行结果我也是可以理解的,两个都是NaN故最终结果是NaN。但是o3的结果就令我非常困惑了。书上的原话是执行valueOf得到NaN会再去调用toString。(后来我看到减法操作,发现如果有valueOf方法则使用valueOf方法的返回结果)那么按照我的理解o3最终是会得到3的。但是实验告诉我结果是NaN。我用的是Chrome浏览器,是不是书上说的已经过时了,还是我理解的不对。希望有人看到这个能评论讨论一下这个内容。这里再顺便说下如果在alert(++o4)之前alert(o4)是会输出2xx的,因为会自动调用在o4自增前o4还是个object,会自动调用toString()方法。而自增后o4已经变成一个Number类型了。
一元加和减操作符
注意这里说的是一元操作符,一元加操作符对于Number类型不会有任何变化(如果是减操作符就是取相反数)。如果是其他类型则执行Number()方法,以下是例子:
var s1 = "01" ;
var s2 = "1.1" ;
var s3 = "z" ;
var b = false ;
var f = 1.1 ;
var o = {
valueOf: function () {
return -1 ;
}
};
s1 = +s1;
s2 = +s2;
s3 = +s3;
b = +b;
f = +f;
o = +o;
位操作符
当对数值应用位操作符时,后台会发生如下转换过程:64位的数值被转换成32位数值,然后执行位操作,最后再将32位的结果转换为64位数值。这样表面看起来就好像是在操作32位数值。但这样会导致一个严重的副效应,再在特殊的NaN和Infinity值应用位操作时,这2个值会被当成0来对待。
按位非 (‘~’)
var num1 = 25 ;
var num2 = ~num1;
alert(num2);
按位非操作其实就相当于取反减一。但其速度会优于取反减一操作。
按位与 (‘&’)
按位与有2个操作数。与运算是在两个值都为1的时候才为1,这里省略例子。
按位或 (‘|’)
按位或有2个操作数。或运算是在两个值都为0的时候才为0,这里省略例子。
按位异或 (‘^’)
按位异或有2个操作数。异或运算是在两个值都不相同的时候才为1,这里省略例子。
左移(‘<<’)
左移运算就是把32位下的后31位(除去符号位)进行左移,右边多出来的空位填0。例子如下:
var a = 2 ;
alert(a << 2 );
右移(有符号右移’>>’,无符号右移’>>>’)
通常来说右移相当于除以2操作。有符号右移与左移类似。无符号右移对于正数来说和有符号右移没有区别。但是对负数进行无符号右移时,由于负数存的是补码,此时会将其当做正数处理,所以一般会造成得到的结果非常大。
布尔操作符
布尔操作符有3个(!, &&, ||),和java中用法相同。以下分别对三个操作符进行说明: 逻辑非(!):只有一个操作数,可以应用任何值,无论这个值是什么都会返回布尔值(注意和下面两个操作符的区别)。其实它的功能总结起来就是先用Boolean()函数对这个值取结果,然后再进行逻辑非运算。所以连续两个逻辑非’!!’的效果和Boolean()是一模一样的。 逻辑与(&&):有两个操作数。在有一个操作数不是布尔值的时候,其返回结果就不一定是布尔值。
alert("12" && true );
alert("" && "34" );
alert("12" && "34" );
alert(true && "34" );
alert(null && "34" );
alert(NaN && null );
alert(undefined && null );
alert(false && null );
因为逻辑与操作符是短路操作符(逻辑或操作符也是),所以上述的结果其实很好理解了。首先会对第一个操作数进行Boolean()操作。如果是false,那么对不起直接返回第一个操作数的原型(原来是什么就返回什么),第二个到底是什么就不管了(即使第二个操作数未定义)。如果第一个是true。再去对第二个操作数进行Boolean()操作,如果还是true,那就返回第二个操作数的原型。那如果第二个操作数是false。那么也会返回第二个操作数的原型。所以总结下来就是( 以下是我的个人总结,如有不对欢迎指出。):
第一个操作数使用Boolean()计算是false,则返回第一个操作数原型。 第一个操作数使用Boolean()计算是true,则返回第二个操作数原型。 逻辑或(||):有两个操作数。在有一个操作数不是布尔值的时候,其返回结果就不一定是布尔值。类比上面的逻辑与操作符有总结如下:
第一个操作数使用Boolean()计算是true,则返回第一个操作数原型。 第一个操作数使用Boolean()计算是false,则返回第二个操作数原型。
alert("12" || true );
alert("" || "34" );
alert("12" || "34" );
alert(true || "34" );
alert(null || "34" );
alert(NaN || null );
alert(undefined || null );
alert(false || null );
小tips:上述逻辑或的特性常用于给函数赋默认值,如下:
function getAjaxResponse(url,method) {
method = method || "get" ;
...
}
/*上述做法当调用getAjaxResponse("hello world!" )时,
*由于method未传,在函数中为undefined,
*/利用逻辑或的特性可以为method赋值"get"
乘性操作符
乘性操作符包括乘除和取余。总结一句话就是如果操作数不是数值类型,利用Number()隐性转换。如果操作数中包含NaN,那么结果是NaN。如果包含Infinity:
Infinity * Infinity = Infinity Infinity / Infinity = NaN Infinity % Infinity = NaN 10 / Infinity = 0 10 / 0 = Infinity 0 / 0 = NaN
加性操作符
加法
console. log (+ 0 + + 0 );
console. log (- 0 + - 0 );
var a;
var b = "123" ;
var c = 123 ;
alert(a + b);
alert(a + c);
var a = {
valueOf: function () {
return 1 ;
},
toString: function () {
return 2 ;
}
}
var b = {
valueOf: function () {
return 4 ;
},
toString: function () {
return 8 ;
}
}
var c = "hello" ;
alert(a);
alert(a + c);
alert(a && c);
alert(a || c);
alert(a + b);
减法操作符
减法同加法没有什么区别,唯一的区别是减法没有截取字符串一说。以下是例子:当遇到操作数不是数值的时候,会隐性的调用Number()方法转成数值。
var a = {
valueOf: function () {
return 1 ;
},
toString: function () {
return 2 ;
}
}
var b = {
toString: function () {
return 8 ;
}
}
var c = "hello" ;
var d = "1" ;
var e = "1xx" ;
alert(a - c);
alert(a - b);
alert(a - d);
alert(a - e);
关系比较符(>, <, >=, <=)
如果两个操作数都是数值,执行数字比较。 如果都是字符串,比较对应的字符编码值。(按高到低) 如果一个是数值,则将另外一个操作数通过Number()转换为数值进行比较。 如果一个操作数是对象,调用valueOf方法。如果没有valueOf方法则调用toString()方法。再按照前三条规则比较。 如果是布尔值则通过Number()转换成数值,再按照前三条。
var a = "123" ;
var d = "123xx" ;
var b = {
valueOf: function () {
return 2 ;
},
toStrong: function () {
return "2" ;
}
}
var c = {
toStrong: function () {
return "2" ;
}
}
alert(a > b);//true 先是valueOf返回数值2 再将"123" 转为数值123 比较得到true
alert(a > c);//false 先是toString返回字符串"2" "123" < "2"
alert(d > 1 || d <= 1 );//false 先是Number()返回NaN NaN不管怎么比较都是false
相等操作符
相等和不相等(==, !=)
如果一个操作数是布尔值,先转成数值再进行比较。 如果一个是字符串,一个是数值,则将字符串转成数值比较(可能得到NaN)。 如果一个是对象,一个不是,则调用该对象的valueOf方法(如果valueOf返回的还是对象则调用toString),通过返回的值的类型再按照上面规则进行比较。 null 和 undefined相等,且不能将其转换成其他值。 如果操作数中有NaN, 相等永远为false。不等永远为true。(NaN != NaN) 如果都是对象,则比较他们是不是同一个对象。如果指向同一个对象返回true。
全等和不全等(===, !==)
全等比较符除了在比较前不转换类型外,其他都与相等操作符一样。(null !== undefined)
条件操作符
var max = (num1 > num2) ? num1 : num2;
赋值操作符
此处简单略过,使用类似 += -=其实主要目的是简化赋值操作。不会带来性能的提升。有以下几个赋值操作:
*= /= %= += -= <<= >>= >>>=
逗号操作符
使用逗号操作符多用于声明多个变量。除此之外,逗号操作符还可以用于赋值。用于赋值时,逗号操作符总会返回表达式中的最后一项。例子如下:
var num1=1 , num2=2 , num3=3 ;
var num = (1 , 2 , 3 , 4 , 5 );