二元加运算符
具体内容在笔记《二元“+”运算符》中。
一元运算符
一元运算符(+、-、++ 和–)具有很高的优先级,而且都是右结合(right-associative)。必要时,它们会将操作数转换为数字。
“+”和“-”既是一元运算符,也是二元运算符。
一元加法(+)
一元加法运算符将非数字操作数操作数转换为数字(或者NaN),并返回转换后的结果。
console.log(+null); // 0
console.log(+undefined); // NaN
console.log(+[]); // 0
console.log(+[1]); // 1
console.log(+[1,2]); // NaN
var date = new Date();
console.log(+date); // 1478338521770
var foo = function () {};
console.log(+foo); // NaN
console.log(+{}); // NaN
console.log(+{a:1}); // NaN
一元减法(-)
同样需要将非数字操作数转换为数字,然后作为结果的符号。
console.log(-null); // -0
console.log(-undefined); // NaN
console.log(-[]); // -0
console.log(-[1]); // -1
console.log(-[1,2]); // NaN
var date = new Date();
console.log(-date); // -1478338521769
var foo = function () {};
console.log(-foo); // NaN
console.log(-{}); // NaN
console.log(-{a:1}); // NaN
自增(++)
书中写的是递增,我习惯称++为自增
自增操作符对操作数进行加一操作,且操作数是一个左值(变量、数组元素、或对象属性),同样会将非数字操作符转换为数字。
// 下面代码中被注释掉的都会报错,因为操作数都不是左值
//console.log(++null);
//console.log(++undefined);
//console.log(++[]);
//console.log(++[1]);
//console.log(++[1,2]);
var arr = [1];
console.log(++arr[0]); // 2
var date = new Date();
console.log(++date); // 1478338521772
var foo = function () {};
console.log(++foo); // NaN
//console.log(++{});
//console.log(++{a:1});
var obj = {a:1};
console.log(++obj.a); // 2
++运算符的返回值依赖于它相对于操作数的位置:
- 在操作数之前,称为前自增,对操作数进行加一操作,并返回计算后的值。
- 在操作数之后,称为后自增,对操作数时行加一操作,但返回未加一的值。
需要注意的是:表达式++x并不总是和x=x+1完全一样。因为x字符串时,++会将其转换为数字,而+则进行字符串连接操作。
var a = 1;
console.log(++a); // 2
//a = a + 1;
//console.log(a); // 2
var b = "1";
console.log(typeof b); // "string"
console.log(++b); // 2
console.log(typeof b); // "number"
//b = b + 1;
//console.log(b); // "11"
可以看到,原来是字符串的,经过自增运算后,变为数字。
另外需要注意的是,后自增运算符和操作数之间不能插入换行符,如果插入了换行符,JavaScript将会把操作数当作一条单独的语句,并在之前补上一个分号。
**自减(–)
–运算符的操作数也是一个左值,它对操作数执行减1操作。同样需要将非数字操作数转换为数字,其他特点与++类似。
位运算符
位运算并不是传统的数学运算,书中将它们归类为算术运算符,因为它们作用于数值类型的操作数并返回数字。
位运算符要求它的操作数是整数,这些整数表示为32位整型,而不是64位浮点型。必要时,位去处符首先将操作数转换为数字,并将数字强制表示为32位整型,这会忽略原格式中的小数部分和任何超过32位的二进制位。
移位运算符要求右操作数在0~31之间。
位运算符会将NaN、Infinity和-Infinity都转换为0,所以任何类型的值都可以作为位运算的操作数。例如:
console.log(~null); // -1
console.log(~undefined);// -1
console.log(~[]); // -1
console.log(~[1]); // -2
console.log(~[1,2]); // -1
var date = new Date();
console.log(~date); // -875337788(我当时运行得到的值)
var foo = function () {};
console.log(~foo); // -1
console.log(~{}); // -1
console.log(~{a:1}); // -1
console.log(1<<(function () {})); // 1
按位与(&)
“&”对它的整型操作数逐位执行布尔与(AND)操作。只有两个操作数对应的位都是1,结果中的这一位才是1。例如:
0x1234 & 0x00FF // 0x0034
按位或(|)
“|”对它的整型操作数逐位执行布尔或(OR)操作。只要有一个操作数中对应的位是1,结果中的这一位就是1。例如:
0x1234 | 0x00FF // 0x12FF
按位异或(^)
“^”对它的整型操作数逐位执行布尔异或(XOR)操作。只有两个操作数对应的位是不相同,结果中的这一位才是1。例如:
0xFF00 ^ 0xF0F0 // 0x0FF0
按位非(~)
“~”是一元运算符,它将操作数的所有位取反。
根据JavaScript中带符号的整数的表示方法,对一个值使用“~”运算符,相当于改变它的符号并减1。例如:
~0x0F // 0xFFFFFFF0或-16
~0xFFFFFFF0 // 0x0F或15
左移(<<)
“<<”将左操作数的二进制位向左移动右操作数个位数,右边的空缺位用0填补。将一个数左移n位,相当于该数乘以2的n次方。例如:
7 << 2 // 28
带符号右移(>>)
“>>”将左操作数的二进制位向右移动右操作数个位数,左边空缺的位由左操作数原来的符号决定,正数则补0,负数则补1。将一个数带符号右移n位,相当于该数除以2的n次方,忽略余数。例如:
7 >> 1 // 3
-7 >> 1 // -4
无符号右移(>>>)
“>>>”和“>>”一样,只是在左边的高位总是填补0,与左操作数原来的符号无关。例如:
-1 >> 4 // -1
-1 >>> 4 // 0x0FFFFFFF
小结
对于位运算符,我在工作中基本没使用到过,不过这些操作符与C++ 的类似,也就不那么陌生。
无符号右移运算在C++中是没有的。
全都是些细节的问题,由于平时基本用不到,所以做下笔记,以后遇到了可以快速的查看。