二元算术运算符

二元算术运算符,包括加法( + )、减法( - )、乘法( * )、除法( / )和求余( % ) 。


加法( + )

在多数程序设计语言中,加法通常是简单的数字运算符,但在ECMAScript中,加法运算有大量的特殊行为, 不仅可以进行数值加法运算,也可以进行字符串连接。

加法运算遵循如下规则:

  • 如果其中一个操作数是对象,则对象会转换为原始值:日期对象通过toString()方法执行转换,其他对象通 过valueOf()方法执行转换。多数对象valueOf()方法无法返回一个原始值,于是会通过toString()方法执行转换。

除了单数值数组会转换为数字外,其他原生对象都会通过toString()方法转换为字符串形式。

  • 在进行了对象到原始值的转换后,如果其中一个操作数是字符串的话,另一个操作数也会转换成字符串, 进行字符串连接;否则,两个操作数都将转换成数字或NaN,进行加法操作。

// 单数值数组和valueOf()返回值为数值的自定义对象会转换为数值
console.log(1 + []);//1
var o = {
    valueOf: function(){
        return -1;
    }
}
console.log(1 + o);//0

// 其他原生对象则转换为字符串
console.log(1 + {});//'1[object Object]'
console.log(1 + [1,2]);//'11,2'
console.log(1 + new Date());//'1Thu Jun 16 2016 10:27:13 GMT+0800 (中国标准时间)'
console.log(1 + /0/);//'1/0/'

如果进行算术加法运算,undefined转换为NaN,null转换为0,false转换为0,true转换为1

console.log(undefined + undefined);//NaN
console.log(null + null);//0
console.log(false + false);//0
console.log(true + true);//2

如果进行字符串连接,undefined转换为'undefined',null转换为'null',false转换为'false',true转换为'true'

console.log('' + undefined);//'undefined'
console.log('' + null);//'null'
console.log('' + false);//'false'
console.log('' + true);//'true'

因此,利用加号运算符的特性,可以利用''+任意类型值转换为字符串
  在数字加法运算中,Infinity和带符号的0的处理较为特殊

Number.MAX_VALUE + Number.MAX_VALUE === Infinity;//true
Infinity + (-Infinity);//NaN
+0 + (-0) === +0;//true

减法( - )

相对加法,减法简单的多,只涉及数字的减法运算。使用Number()转型函数将非数值类型转换为数值或NaN。

console.log(1 - {});//NaN
console.log(1 - [1,2]);//NaN
console.log(1 - /0/);//NaN
console.log(1 - []);//1

加法有一个特殊之处,在于时间Date对象进行加法运算时使用toString()转换为字符串,而在其他数学运算,
包括减、乘、除、求余等运算中,都是使用Number()转换函数将时间Date对象使用valueOf()转换为数字。

console.log(new Date() + 1);//'Thu Jun 16 2016 11:11:49 GMT+0800 (中国标准时间)1'
console.log(new Date() - 1);//1466046941641

undefined转换为NaN,null转换为0,false转换为0,true转换为1

console.log(1 - undefined);//NaN
console.log(1 - null);//1
console.log(1 - false);//1
console.log(1 - true);//0

乘法( * )

乘法操作符由星号(*)表示,用于计算数值的乘积,会通过Number()转型函数将非数值类型转换为数值或NaN。

+ Infinity * 0;//NaN
- Infinity * 0;//NaN
Infinity * 非0数值;//Infinity或-Infinity
Infinity * Infinity;//Infinity

除法( / )

除法操作符由一个斜线(/)表示,执行第一个操作数除以第二个操作数的运算,也会通过Number()转型函数将
非数值类型转换为数值或NaN。

Infinity / Infinity;//NaN
0 / 0;//NaN
非0数值 / 0;//Infinity或-Infinity
Infinity / 0;//Infinity
Infinity / 非0数值;//Infinity

取模( % )

求模(余数)操作符是由一个百分号(%)表示,是第一个操作数除以第二个操作数的余数。

//r是余数,n是被除数,d是除数,
//q是整数,在n/d为负时为负,在n/d为正时为正,它应该在不超过n和d的商的前提下尽可能大
r = n - (d * q)

求模结果与第一个操作数的符号保持一致

console.log(5 % 2);//1
console.log(5 % -2);//1
console.log(-5 % 2);//-1
console.log(-5 % -2);//-1

被除数是Infinity,或除数是0,则求模结果是NaN

Infinity % 0 = NaN
Infinity % Infinity = NaN
Infinity % 非0数值 = NaN
非0数值 % 0 = NaN

在多数编程语言中,求模运算符只接受整数为操作数,而在ECMAScript中,还接受浮点操作数,
但由于浮点数不是精确的值,无法得到完全准确的结果。

console.log(6.5 % 2.1);//0.19999999999999973