操作符
1.一元操作符
只能操作一个值的操作符叫做一元操作符,一元操作符有递增(递减)操作符以及一元加(减)操作符。
递增递减操作符分为前置递增(递减)操作符和后置递增(递减)操作符,不管是前置还是后置的递增(递减)操作符,其使用方式与java中的递增递减操作符一样,有区别的地方就是javascript中的递增递减操作符可以对非数字类型的值进行操作,看下面的例子:
a.对包含有效数字字符的字符串执行递增递减操作时,会将字符串转换成数字后再执行递增递减操作。字符串最后转换为number类型。
b.对于不能转换成数字的字符串,返回NaN,且原字符串变为NaN。
c.对于布尔型值,true转换为1,false转换为0后执行递增递减操作。
d.对象类型,先执行对象的valueOf()方法,对取出的值执行上述的方式进行递增递减,如果返回NaN,那么再执行toString()方法,同样采用上述的方式进行递增递减。
前置递增递减操作符,变量的值都是在语句被求值以前改变;后置递增递减操作符,变量的值都是在语句被求值以后改变。
对于一元加或者减操作符,一元加操作符以(+)表示,一元减操作符以(-)表示。对于数字使用一元加或者减操作符与数学中的加减操作符一样,但是在对非数字值使用一元加减操作符时,相当于对当前值使用Number()函数。具体的操作如下所示:
2.位操作符
位操作符实际上是操作内存中表示数值的位来操作数值。ECMAScript中的所有数值都是以IEEE-754 64位格式存储,但是位操作符并不是直接操作64位的值,而是先把64位值转换为32位,然后执行操作,将操作结果再转换回64位。
对于有负号的整数,32位中的前31位存储数值,32位是符号位,1表示负数,0表示正数。其中正数以纯二进制的格式存储,31位中的每一位都是2的指数次幂,2的指数从0开始,一直向后类推。没有用到的位以0填充。负数同样用二进制存储,但是使用的格式是二进制补码(计算方式请自行百度)。在ECMAScript中负数的二进制表示形式是该负数的绝对值的二进制前面加上负号,例如18的二进制码是10010,那么-18的二进制码就是-10010。
ECMAScript中对数值应用位操作符时,首先64位的数值会被转换成32位,然后执行位操作,操作完成之后将32位的结果再转换回64位。其中NaN和Infinit应用位操作符时,会当做0处理。对于非数字型值,自动使用Number()函数转换成数值后再进行位操作,得到一个数字结果。
2.1按位非
使用波浪线(~)表示,按位非操作符返回数值的反码,如下例子所示:
可以看到对25执行按位非操作之后,结果返回-26,-26的二进制码是26的二进制码前面加上负号,本来应该是二进制补码,但是在ECMAScript中显示的就是整数的二进制码的负值。同时上述例子可以看出按位非操作符等价于当前值的负值减一。
2.2.按位与|按位或|按位异或
按位与操作符用(&)表示,该操作符对两个操作数进行操作,按照下表中的规则依次比较两个数值对应位置的值,返回一个数值。比较规则如下(两个数值的相同位置上的值都为1结果为1,其他的结果都是0):
第一个数值的位 |
第二个数值的位 |
比较结果 |
1 |
1 |
1 |
1 |
0 |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
例子如下:
按位或操作符使用(|)表示,同样是对两个操作数操作,对比规则如下所示(两个数值的相同位置上的值只要有一个为1,结果就是1):
第一个数值的位 |
第二个数值的位 |
比较结果 |
1 |
1 |
1 |
1 |
0 |
1 |
0 |
1 |
1 |
0 |
0 |
0 |
例子如下:
按位异或使用(^)表示,操作两个操作数,比较规则(两个数值相同位置上的值相同,结果是0,不同结果是1):
第一个数值的位 |
第二个数值的位 |
比较结果 |
1 |
1 |
0 |
1 |
0 |
1 |
0 |
1 |
1 |
0 |
0 |
0 |
例子如下:
2.3.左移
左移使用(<<)表示。如下所示:
通过上面的例子可以看出,左移操作符将数值的所在位向左移动指定的位数,也就是向左了5位,移动后原数值的右侧空出五个位置,用0来补充空位。注意:左移操作符不会影响操作数的符号位,也就是说-11向左移动5位结果是-352。
2.4.有符号的右移|无符号右移
有符号的右移用(>>)表示,先看例子:
有符号的右移会将数值向右移动指定的位数,但是保留符号位,也就是说有符号的右移是不会造成数值符号改变的,右移造成的空位用符号位的值来填充,以得到一个完整的值。
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
|
右移5位之后,结果为4,二进制码如下所示:
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
无符号的右移用(>>>)表示,这个操作符会把数值的所有32位都向右移动,对于正数来说,无符号右移和有符号右移得到的结果是一样。但是对于负数来说,结果却是会发生改变,原因主要有两点:第一,无符号右移是以0来填充空位,有符号右移是以符号位的值来填充空位;第二,无符号的右移会把负数的二进制码当成正数的二进制码,而且,由于负数的二进制码以其绝对值的二进制码补码形式存在,因此就会导致无符号右移后的结果非常大。
例子如下所示:
如上所示,-64的二进制码为64的二进制码补码,也即1111111111111111111111111000000,
无符号右移操作会把这个值当做正数的二进制码,然后再右移5位形成00000111111111111111111111111110,转换为十进制数字就是134217726。
3.布尔操作符
3.1.逻辑非
逻辑非操作符用(!)表示,可以对ECMAScript中的任何值使用该操作符,返回一个布尔值,对值使用该操作符时,会先将当前值转换为布尔值,然后再对其取反。具体的转换规则如下:
i.操作数是对象,返回false;
ii.操作数是空字符串,返回true;
iii.操作数是非空字符串,返回false;
iv.操作符是数值0,返回true;
vi.操作数是非0数值(包括Infinity),返回false;
vii.操作数是null,返回true;
viii.操作数是NaN,返回true;
ix.操作数是undefined,返回true;
3.2.逻辑与
逻辑与操作符使用(&&)符号表示,与java中一样,必须两个操作数都是true时,结果才为true,如果有一边为false,那么结果就是false。但是javascript中,两个操作数的数据类型不一定都是布尔型的,也可以是其他的数据类型,此时返回结果的判断规则如下所示:
i.如果第一个操作数是对象,那么返回第二个操作数;
ii.如果第二个操作数是对象,那么只有在第一个操作数返回true时才会返回该对象;
iii.如果两个操作数都是对象,那么返回第二个操作数;
iv.如果一个操作数是null,那么返回null;
v.如果一个操作数是NaN,那么返回NaN;
vi.如果一个操作数是undefined,那么返回undefined;
注意:逻辑与操作属于短路操作,只要第一个操作数能够确定结果,第二个操作数就不会再求值。切两个操作数中不能出现未声明的变量,否则会导致错误。
3.3.逻辑或
逻辑或操作符用(||)表示,即两个操作数中有一个为true,那么结果就是true。同样,两个操作数中如果有一个不是布尔值,逻辑或也不一定返回布尔值,具体规则如下:
i.如果第一个操作数是对象,那么返回对象;
ii.如果第一个操作数的求值结果是false,那么返回第二个操作数;
iii.如果两个操作数都是对象,那么返回第一个操作数;
iv.如果两个操作数都是null,那么返回null;
v. 如果两个操作数都是NaN,那么返回NaN;
vi. 如果两个操作数都是undefined,那么返回undefined;
4.乘性操作符
ECMAScript中规定了三种乘性操作符,分别是乘法、除法和求模,这三种操作符与java中的操作一样,不同的是当操作符不是数值的时候,会执行自动的类型转换。
4.1.乘法
乘法操作符用(*)表示,用语计算两个数值的乘积,当操作数为特殊情况时,处理规则如下:
i.如果两个操作数都是数值,按照数学的乘法计算即可,但是当计算结果超过ECMAScript规定的数值范围时,返回Infinity或者-Infinity;
ii.如果有一个操作数是NaN,那么返回NaN;
iii.如果是Infinity与0相乘,结果是NaN;
iv.如果Infinity与非零数值相乘,结果是Infinity或者-Infinity,符号取决于非零数值;
v.如果是Infinity与Infinity相乘,结果还是Infinity;
vi.如果有一个操作数不是数值,那么调用Number()函数转换为数值之后,再执行上述操作。
4.2. 除法
除法操作符用(/)表示,表明第二个操作数除第一个操作数的计算,同样,特殊情况处理规则如下:
i.如果两个操作数都是数值,那么执行数学计算即可,如果商超过ECMAScript规定的数值范围,那么返回Infinity或者-Infinity。
ii.如果有一个操作数是NaN,那么返回NaN;
iii.如果是Infinity被Infinity除,结果是NaN;
iv.如果是0除以0,结果是NaN;
v.如果非零的有限数被0除,那么返回Infinity或者-Infinity,符号取决于被除数;
vi.如果是Infinity被任何非零有限数除,那么返回结果是Infinity或者-Infinity。
vii. 如果有一个操作数不是数值,那么调用Number()函数转换为数值之后,再执行上述操作。
4.3.求模
求模操作符由(%)表示,表示第一个操作数除以第二个操作数所得的余数,处理规则如下:
i.如果两个操作数都是数值,执行数学运算即可;
ii.如果被除数无限大,除数有限大,那么返回NaN;
iii. 如果被除数无限大,除数是0,那么返回NaN;
iv.如果是Infinity除以Infinity,结果是NaN;
v.如果被除数是有限大的数值,除数是无限大的数值,返回被除数;
vi.如果被除数是0,结果是0;
vii. 如果有一个操作数不是数值,那么调用Number()函数转换为数值之后,再执行上述操作。
5.加性操作符
5.1.加法
加法操作符使用(+)表示,如果两个操作数都是数值,执行常规的加法运算,根据以下规则计算结果:
i.如果有一个数是NaN,那么结果就是NaN;
ii.如果是Infinity加Infinity,结果是Infinity;
iii.如果是-Infinity加-Infinity,结果是-Infinity;
iv.如果是Infinity加-Infinity,结果是NaN;
v.如果是+0加-0,结果是+0;
vi.如果是+0加+0,结果是+0;
vii.如果是-0加-0,结果是-0;
如果有一个操作符是字符串,那么久需要使用以下规则:
- 如果两个操作数都是字符串,那么把两个字符串拼接起来;
- 如果只有一个操作数是字符串,那么将另一个操作数转换成字符串,然后把两者拼接起来;
如果有一个操作数是对象、数值或者布尔值, 则调用他们的toString()方法取到相应的字符串,再应用前面关于字符串的规则,如果是undefined或者null,调用String()函数获取到对应的字符串”undefined”和”null”;
5.2.减法
减法操作符使用(-)表示,具体的运算规则如下所示:
i.如果两个操作符都是数值,那么数学运算即可;
ii.如果一个操作数是NaN,结果是NaN;
iii. 如果是Infinity减Infinity,结果是NaN;
iv. 如果是-Infinity减-Infinity,结果是NaN;
v. 如果是Infinity减-Infinity,结果是Infinity;
vi. 如果是-Infinity减Infinity,结果是-Infinity;
vii. 如果是+0减+0,结果是+0;
viii. 如果是+0减-0,结果是-0;
ix. 如果是-0减-0,结果是+0;
x.如果一个操作数是字符串、布尔值、null或者undefined,那么调用Number()函数转换为数值后再根据前面的规则执行减法计算;
xi.如果有一个操作数是对象,那么调用对象的valueOf()方法取得表示该对象的值,如果得到的值是NaN,减法的结果就是NaN,如果对象没有valueOf()方法,那么就调用toString()方法并将取到的字符串转换为数字。
6.关系操作符
ECMAScript中使用<,>,<=,>=这几个关系操作符比较两个值的大小,具体的比较规则如下:
i.如果两个操作数都是数值,那么进行数学运算即可;
ii.如果两个操作数都是字符串,那么比较两个字符串对应的字符编码值;
iii.如果一个操作数是数值,则将另一个操作数转换为一个数值,然后执行数值比较;
iv.如果一个操作数是对象,先调用该对象的valueOf()方法,用得到的值按照前面的规则比较,如果对象没有valueOf()方法,那么就调用对象的toString()方法,用得到的值按照前面的规则比较。
v.如果一个操作数是布尔值,先将其装换为数值后再进行比较。
下面看两个例子:
这个例子中小写字母a分别和小写字母b以及大写字母B比较,发现a小于b但是大于B,这是由于两个字符串比较,实际上是比较两个字符串中对应位置的每个字符的字符编码值,大写字母的字符编码值全部小于小写字母的字符编码值,因此a<B返回false。
第二个例子:
这个例子中,首先是字符串”23”和字符串”3”比较,比较的结果是”23”小于”3”,原因和上一个例子一样,两个字符串比较的是字符编码,”23”的字符编码是50,而”3”的字符编码是51,因此返回结果为true。对于字符串”23”和数字3比较,由于一个操作数是数字,因此会将字符串转换为数字后比较,因此返回false。
7.相等操作符
相等操作符分为两种类型,第一种是相等和不相等,当需要转换时,先转换再进行比较;第二种是全等和不全等,此时不进行转换,直接进行比较。
7.1.相等和不相等
相等操作符用(==)表示,不相等操作符用(!=)表示,这两个操作符都会对操作数进行强制转型,然后才比较两者的相等与否。
在强制转型时,相等和不相等操作符遵循以下规则:
i.如果有一个操作数是布尔值,那么先将其转换为数字,false为0,true为1;
ii.如果一个操作数是字符串,另一个操作数是数字,那么需要先将字符串转换为数字后再比较;
iii.如果一个操作符时对象,另一个不是,那么需要调用对象的valueOf()方法,用得到的基本类型值按照前面的规则比较;
iv.null和undefined是相等的;
v.在比较之前,不能将null或者undefined转换成其他的值;
vi.如果有一个操作数是NaN,那么相等操作符返回false,不相等操作符返回true,如果两个操作数都是NaN,相等操作符返回false;
vii.如果两个操作数都是对象,那么则比较两个操作符指向的是否是同一个对象,如果是,那么相等操作符返回true,否则返回false;
7.2.全等和不全等
全等和不全等与相等和不相等之间唯一的区别就是在比较之前不进行操作数转换,全等操作符用(===)表示,当两个操作数不需要经过转换就相等时返回true,不全等用(!==)表示。
注意:null == undefined返回true是由于两者是类似的值,但是null === undefined返回false是由于两者不是一个类型,推荐使用全等和不全等操作符。
8.条件操作符、赋值操作符、逗号操作符
8.1.条件操作符
条件操作符就是我们所属的三元比较,表示方式为:boolean_condition ? true_value : false_value。当条件为true时,返回true_value,当条件为false时,返回false_value。
8.2.赋值操作符
赋值操作符的作用就是把操作符右侧的值赋给左侧的变量,最简单的赋值操作符就是=,其他的操作符有*=,/=,%=,+=,-=,<<=(左移赋值),>>=(有符号右移赋值),>>>=(无符号右移赋值)
8.3逗号操作符
使用逗号操作符可以在一条语句中执行多个操作,如下所示:
var num1 = 1 , num2 = 2 , num3 = 3;
操作符部分终于结束了,好累啊。