操作符

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()转型函数一样对这个值执行转换。
布尔值falsetrue将被转换为01,字符串值会被按照特殊的规则进行解析,对象是先调用它们的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位数值。
这个转换过程导致严重的副效应,对特殊的NaNInfinity值应用位操作时,这里两个值都会被当成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的值为nullundefined时,会将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,符号取决于操作数的符号。
  • 如果是InfinityInfinity相乘,则结果为Infinity
  • 如果有一个操作数不是数值,则在后台调用Number()将其转换为数值,再应用上述规则。

除法

除法操作符由一个斜线符号/表示,执行第二个操作数除第一个操作数的计算。

var result = 66/11;

与乘法操作符类似,除法操作符对待特殊值也有特殊的处理规则,规则如下:

  • 如果操作数都是数值,执行常规的除法计算。如果商超过了ECMAScript数值的表示范围,则返回Infinity-Infinity
  • 有一个操作数是NaN,则结果是NaN
  • 如果是InfinityInfinity除,则结果是NaN
  • 如果是00除,则结果是NaN
  • 如果是非零的有限数被零除,则结果是Infinity-Infinity,取决于有符号操作数的符号。
  • 如果是Infinity被任何非零数除,则结果是Infinity-Infinity,取决于有符号操作数的符号。
  • 如果有一个操作数不是数值,则在后台调用Number()将其转换为数值,再应用上述规则。

求模

求模操作符由%表示,用法如下:

var result = 26%5;  //1

与另外两个乘性操作符类似,求模操作符会遵循以下特殊规则来处理特殊的值:

  • 如果操作数都是数值,执行常规的除法计算,返回除得的余数。
  • 如果被除数是无穷大值,除数是有限大值,则结果是NaN
  • 如果被除数是有限大数值,除数是0,则结果是NaN
  • InfinityInfinity除,结果是NaN
  • 如果被除数是0,则结果是0。
  • 如果有一个操作数不是数值,则在后台调用Number()将其转换为数值,再应用上述规则。

加性操作符

加法和减法属于加性操作符,在ECMAScript中,这两个操作符有一系列特殊行为。

加法

加法操作符用法如下:

var result = 1 + 2;

如果两个操作符都是数值,执行常规的加法计算,然后根据下列规则返回结果:

  • 如果有一个操作数是NaN,则结果是NaN
  • 如果是InfinityInfinity,则结果是Infinity
  • 如果是-Infinity-Infinity,则结果是-Infinity
  • 如果是Infinity-Infinity,则结果是NaN
  • 如果是+0+0,则结果是+0
  • 如果是-0-0,则结果是-0
  • 如果是+0-0,则结果是+0
  • 如果两个操作数都是字符串,则将第二个操作数与第一个操作数拼接起来。
  • 如果只有一个操作数是字符串,则将另一个操作数转换为字符串,然后再将两个字符串拼接起来。
  • 如果有一个操作数是对象、数值或布尔值,则调用它们的toString()方法取得相应的字符串值,然后再应用前面关于字符串的规则。对于undefinednull,则分别调用String()函数并取得字符串"undefined""null"

减法

减法操作符,是另一个极为常用的操作符,其用法如下所示:

var result = 2 - 1;

与加法操作符类似,ECMAScript中的减法操作符在处理各种类似数据转换时,同样需要遵循一些特殊规则,如下所示:

  • 两个操作数都是数值,执行常规算术减法操作并返回结果。
  • 如果有一个操作数是NaN,则结果是NaN
  • 如果是InfinityInfinity,则结果是NaN
  • 如果是-Infinity-Infinity,则结果是NaN
  • 如果是Infinity-Infinity,则结果是Infinity
  • 如果是-InfinityInfinity,则结果是-Infinity
  • 如果是+0+0,则结果是+0
  • 如果是+0-0,则结果是-0

总结

  • NaN在逻辑运算符中相当于false,在位运算中相当于0,其余运算结果均为NaN

  • 逻辑非可以把任意类型转换为truefalse

  • 逻辑与和逻辑或的运算结果可能为ObjectundefinednullNaNtruefalse

与C++/Java不同之处

  • JavaScript可以对任何类型的值进行自增,自减,相加,相减的操作。