JavaScript提升系列(五):操作符
操作符
ECMA-262描述了一组用于操作数据值的操作符,包括算数操作符,位操作符,关系操作符和相等操作符。
一元操作符
只能操作一个值的操作符叫做一元操作符。
递增和递减
递增和递减操作符借鉴于C语言,而且各有两个版本:前置型和后置型。
var age1 = 29;
var nextAge1 = ++age1; //nextAge=30,age = 30,前置递减型。
var age2 = 29;
var nextAge2 = age2++; //nextAge=29,age = 30,后置递减型。
var age3 = 29;
var prevAge3 = --age3; //prevAge = 28,age = 28,前置递减。
var age4 = 29;
var prevAge4 = age3--; //prevAge = 29,age = 28,后置递减。
所有这4个操作符对任何值都适用,也就是它们不仅适用于整数,还可以用字符串,布尔值,浮点数和对象。
在应用不同值时,递增和递减操作符遵循以下规则:
- 应用于包含有效数字字符的字符串时,先将其转换为数字值,再执行递增或递减操作。字符串变量变成数值变量。
var str = "1234";
var ret = ++str1; // ret = 1235,str = 1235,str也收到副作用影响,变成整数。
var str = "";
var ret = ++str; // ret = 1, str = 1。
- 应用于不包含有效数字字符的字符串时,将变量的值设置为NaN。字符串变量变成数值变量。
var str2 = "1234abcd";
var ret2 = ++str2; // ret2 = NaN,str2 = NaN,str2一开始是无效字符
- 应用于布尔值
false
时,先将其转换为0,再执行加减1操作,布尔值变量变成数值变量。
var b = false;
++b; //b = 1
- 应用于布尔值
ture
时,先将其转换为1,再执行加减1操作,布尔值变量变成数值变量。
var b = true;
++b; //b = 2
- 应用于浮点数值时,执行加减1操作。
var f = 1.1;
++f; //f = 2.1
- 应用于对象时,先调用
valueOf()
方法以取得一个可供操作的值,然后对该值应用前述规则。如果结果是NaN
,则在调用toString()
方法后再应用前述规则。
var o = {
valueOf:function(){
return -1;
}
}
alert(++o); // 0
一元加和减操作符
一元加操作符以加号(+)表示,表示正数,放在数值前面,不会对数值产生任何影响。
var num = 25;
num = +num; //num 仍然是25
在对非数值应用一元加操作符时,该操作符会像Number()
转型函数一样对这个值执行转换。
布尔值false
和true
将被转换为0
和1
,字符串值会被按照特殊的规则进行解析,对象是先调用它们的valueOf()
方法和(或)toString()
方法,再转换得到的值。
var s1 = "01";
var s2 = "1.1";
var s3 = "z";
var b = false;
var f = 1.1;
var o = {
valueOf:function(){
return -1;
}
}
var num1 = +s1; // num1 = 1, s1 = "01"
var num2 = +s2; // num2 = 1.1, s2 = "1.1"
var num3 = +s3; // num3 = NaN;
var num4 = +b; // num4 = 0
var num5 = +f; // num5 = 1.1;
var num6 = +o; // num6 = -1;
一元减操作符以减号(-)表示,主要用于表示负数,下例演示了这个简单的转换过程:
var num1 = 25;
var num2 = -num1; //num2 = -25, num1 = 25
一元减操作数应用于非数值时,遵循与一元加操作符相同的规则,最终将结果转换为负数。
位操作符
在ECMAScript中,当对数值应用位操作符时,后台会发生如下转换过程:64位的数值被转换为32位数值,然后执行位操作,最后再将32位数值转换为64位数值。
这个转换过程导致严重的副效应,对特殊的NaN
和Infinity
值应用位操作
时,这里两个值都会被当成0
来处理。
各种位操作符的执行过程就不具体展开讨论了,在这里总结以下位操作符都有以下:
- 按位与
&
- 按位取反
~
- 按位或
|
- 异或
^
- 左移
<<
- 右移
>>
布尔操作符
布尔操作符一共有3个:与、或、非,都可以应用于ECMAScript中的任何值。
逻辑与
逻辑与由两个和号(&&)表示,有两个操作数,例子如下:
var result = true && false;
真值表如下:
第一个操作符 | 第二个操作符 | 结果 |
---|---|---|
true | true | true |
true | false | false |
false | true | false |
false | false | false |
**逻辑与操作符可以应用于任何类型的操作数,**而不仅仅是布尔值,其遵循以下规则: |
- 第一个操作数是对象,返回第二个操作数。
- 如果第二个操作数是对象,则只有第一个操作数的求值结果为
true
的情况下返回该对象。 - 如果两个操作数都是对象,则返回第二个对象。
- 任意操作数为
null
,返回null
。 - 任意操作数为
undefined
,则返回undefined
。 - 任意操作数为
NaN
,则返回NaN
。
逻辑与操作属于短路操作,如果第一个操作数能够决定结果,那么就不会再对第二个操作数求值。
var found = true;
var result = (found && someUndefinedVariable); //发生错误,Reference Error。
alert(found); //不会执行
如果像下面这个例子一样,将found
的值设置为false,就不会发生错误了。
var found = false;
var result = (found && someUndefinedVariable); //不会发生错误
alert(result); //输出“false”
逻辑或
逻辑或操作符由两个竖线符号(||)表示,有两个操作数,其真值表如下:
第一个操作数 | 第二个操作数 | 结果 |
---|---|---|
Ture | Ture | True |
Ture | False | True |
False | Ture | True |
False | False | False |
如果有一个操作数不是布尔值,逻辑或也不一定返回布尔值,其遵循的规则如下: |
- 如果第一个操作数为对象,则返回第一个操作数。
- 如果第一个操作数的求值结果为
false
,则返回第二个操作数。 - 如果两个操作数都是对象,则返回第一个操作数。
- 如果两个操作数都是
null
,则返回null
。 - 如果两个操作数都是
NaN
,则返回NaN
。 - 如果两个操作数都是
undefined
,则返回undefined
。
与逻辑与一样,逻辑或操作符也是短路操作符,如果第一个操作数的求值结果为true
,就不会对第二个操作数求值了。
var found = true;
var result = (found || someUndefinedVariable); //不会发生错误
alert(result); //弹出窗口"true"
我们可以逻辑或的这一行为来避免为变量赋null
值或undefined
值。
var myObject = preferredObject || backupObject;
在这个例子中,变量myObject
将被优先赋予preferredObject
变量的值,当preferredObject
的值为null
或undefined
时,会将backupObject
的值赋给myObject
。
ECMAScript程序的赋值语句经常会使用这种模式。
逻辑非
逻辑非操作符由一个叹号(!)开始,无论这个值是什么数据类型,这个操作符都会返回一个布尔值,其规则如下:
- 如果操作数是对象,返回
false
。 - 如果操作数是空字符串,返回
true
。 - 如果操作数是非空字符串,返回
false
。 - 如果操作数是数值
0
,返回true
。 - 如果操作数是任意非
0
数值(包括Infinity
),返回false
。 - 如果操作数是
null
,返回true
。 - 如果操作数是
NaN
,返回true
。 - 如果操作数是
undefined
,返回true
。
alert(!false); //true
alert(!{}); //false
alert(!"blue"); //false
alert(!""); //true
alert(!0); //true
alert(!NaN); //true
alert(!null); //true
alert(!undefined); //ture
逻辑非操作符也可以用于将一个值转换为其对应的布尔值,同时使用两个逻辑非操作符最终结果与Boolean()
函数返回相同。
alert(!!"blue"); //true
alert(!!""); //false
alert(!!0); //false
alert(!!NaN); //false
乘性操作符
ECMAScript定义了3个乘性操作符:乘法、除法和求模。这些操作符与其他语言的相应操作符类似,只不过操作数为非数值的情况下会执行自动的类型转换。
如果参与乘性操作符的操作数不是数值,后台会先使用Number()
转型函数将其转为数值。
也就是说,空字符串被当作0,布尔值true
将被当作1。
乘法
乘法操作符由星号(*)表示,用于计算两个数值的乘积。例如:
var result = 34 * 56;
在处理特殊值的情况下,乘法操作符遵循以下原则:
- 如果操作数都是数值,执行常规乘法计算。如果乘积超过了ECMAScript数值的表示范围,则返回
Infinity
或-Infinity
。 - 如果有一个操作数是
NaN
,则结果是NaN
。 Infinity
与0相乘,结果是NaN
。Infinity
与非0数值相乘,结果为Infinity
或-Infinity
,符号取决于操作数的符号。- 如果是
Infinity
与Infinity
相乘,则结果为Infinity
。 - 如果有一个操作数不是数值,则在后台调用
Number()
将其转换为数值,再应用上述规则。
除法
除法操作符由一个斜线符号/
表示,执行第二个操作数除第一个操作数的计算。
var result = 66/11;
与乘法操作符类似,除法操作符对待特殊值也有特殊的处理规则,规则如下:
- 如果操作数都是数值,执行常规的除法计算。如果商超过了ECMAScript数值的表示范围,则返回
Infinity
或-Infinity
。 - 有一个操作数是
NaN
,则结果是NaN
。 - 如果是
Infinity
被Infinity
除,则结果是NaN
。 - 如果是
0
被0
除,则结果是NaN
。 - 如果是非零的有限数被零除,则结果是
Infinity
或-Infinity
,取决于有符号操作数的符号。 - 如果是
Infinity
被任何非零数除,则结果是Infinity
或-Infinity
,取决于有符号操作数的符号。 - 如果有一个操作数不是数值,则在后台调用
Number()
将其转换为数值,再应用上述规则。
求模
求模操作符由%
表示,用法如下:
var result = 26%5; //1
与另外两个乘性操作符类似,求模操作符会遵循以下特殊规则来处理特殊的值:
- 如果操作数都是数值,执行常规的除法计算,返回除得的余数。
- 如果被除数是无穷大值,除数是有限大值,则结果是
NaN
。 - 如果被除数是有限大数值,除数是0,则结果是
NaN
。 Infinity
被Infinity
除,结果是NaN
。- 如果被除数是0,则结果是0。
- 如果有一个操作数不是数值,则在后台调用
Number()
将其转换为数值,再应用上述规则。
加性操作符
加法和减法属于加性操作符,在ECMAScript中,这两个操作符有一系列特殊行为。
加法
加法操作符用法如下:
var result = 1 + 2;
如果两个操作符都是数值,执行常规的加法计算,然后根据下列规则返回结果:
- 如果有一个操作数是
NaN
,则结果是NaN
。 - 如果是
Infinity
加Infinity
,则结果是Infinity
。 - 如果是
-Infinity
加-Infinity
,则结果是-Infinity
。 - 如果是
Infinity
加-Infinity
,则结果是NaN
。 - 如果是
+0
加+0
,则结果是+0
。 - 如果是
-0
加-0
,则结果是-0
。 - 如果是
+0
加-0
,则结果是+0
。 - 如果两个操作数都是字符串,则将第二个操作数与第一个操作数拼接起来。
- 如果只有一个操作数是字符串,则将另一个操作数转换为字符串,然后再将两个字符串拼接起来。
- 如果有一个操作数是对象、数值或布尔值,则调用它们的
toString()
方法取得相应的字符串值,然后再应用前面关于字符串的规则。对于undefined
和null
,则分别调用String()
函数并取得字符串"undefined"
和"null"
。
减法
减法操作符,是另一个极为常用的操作符,其用法如下所示:
var result = 2 - 1;
与加法操作符类似,ECMAScript中的减法操作符在处理各种类似数据转换时,同样需要遵循一些特殊规则,如下所示:
- 两个操作数都是数值,执行常规算术减法操作并返回结果。
- 如果有一个操作数是
NaN
,则结果是NaN
。 - 如果是
Infinity
减Infinity
,则结果是NaN
。 - 如果是
-Infinity
减-Infinity
,则结果是NaN
。 - 如果是
Infinity
减-Infinity
,则结果是Infinity
。 - 如果是
-Infinity
减Infinity
,则结果是-Infinity
。 - 如果是
+0
减+0
,则结果是+0
。 - 如果是
+0
减-0
,则结果是-0
。
总结
-
NaN
在逻辑运算符中相当于false
,在位运算中相当于0
,其余运算结果均为NaN
。 -
逻辑非可以把任意类型转换为
true
或false
。 -
逻辑与和逻辑或的运算结果可能为
Object
、undefined
、null
、NaN
、true
、false
。
与C++/Java不同之处
- JavaScript可以对任何类型的值进行自增,自减,相加,相减的操作。