javascript篇-----操作符

  ECMA-262描述了一组用于操作数据值的操作符,包括算数操作符 、位操作符、关系操作符和相等操作符。ECMAScript操作符的与众不同之处在于,它们能够适用于很多值,例如字符串、数字值、布尔值、甚至对象。不过,在应用于对象时,相应的操作符通常都会调用对象的valueOf()和toString()方法,以便取得可以操作的值。

一元操作符

  顾名思义,一元操作符就是只能操作一个值的操作符,它包括递增和递减操作符、一元加和减操作符四种,下面会都会讨论到。

递增和递减操作符

  递增和递减操作符都各有两个版本:前置型和后置型。从字面上理解,前置型就是操作符位于要操作的变量之前,而后置型则位于要操作的变量之后。

1 {
2   var age = 29;
3   // 前置型
4   ++ age
5   -- age
6   // 后置型
7   age ++
8   age --
9 }

  虽说前置递增(递减)和后置递增(递减)在一般情况的使用上,它们得到运算结果是一致的,都可以理解为以下代码的等价

1 {
2   var age = 29;
3   age = age + 1;
4   // 在运算结果上等价于age++和++age
5   var index = 7;
6   age = age - 1;
7   // 在运算结果上等价于age--和--age
8 }

   但是,它们两者的实际的运算过程上是存在很大区别的。前置递增(递减)操作会在包含它们的语句被求值之前执行,而后置递增(递减)操作则会在包含它们的语句被求值之后执行。下面的代码展示了这个过程的区别。

 1 {
 2   // 后置递增
 3   var num1 = 2;
 4   var num2 = 20;
 5   var num3 = num1++ + num2; // 结果为22,过程为 num3[22] = num1[2] + num2[20]; num1[3] = num1[2] + 1;
 6   var num4 = num1 + num2; // 结果为23,过程为 num4[23] = num[3] + num2[20];
 7   // 前置递增
 8   var num5 = 2;
 9   var num6 = 20;
10   var num7 = ++num5 + num6; // 结果为26,过程为 num5[3] = num5[2] + 1; num7[23] = num5[3] + num6[20];
11   var num8 = num5 + num6; // 结果为23,过程为 num8[23] = num5[3] + num6[20];
12 }

   递增和递减操作符不仅适用于整数,还可以用于字符串、布尔值、浮点数值和对象。在应用于不同的值时,递增和递减操作符遵循下列规则。

  • 在应用于一个包含有效数字字符的字符串时,先将其转换为数字值,再执行加减1的操作。字符串变量变成数值变量。
  • 在应用于一个不包含有效数字字符的字符串时,将变量的值设置为NaN。字符串变量变成数值变量。
  • 在应用于布尔值false时,先将其转换为0再执行加减1的操作。布尔值变量变成数值变量。
  • 在应用于布尔值true时,先将其转换为1再执行加减1的操作。布尔值变量变成数值变量。
  • 在应用于浮点数值时,执行加减1的操作。
  • 在应用于对象时,先调用对象的valueOf()方法以取得一个可供操作的值。然后对该值应用前述规则。如果结果时NaN,则在调用toString()方法后在应用前述规则。对象变量变成数值变量。
 1 {
 2   var s1 = '1';
 3   var s2 = 'z';
 4   var b = true;
 5   var f = 1.2;
 6   var o = {
 7     valueOf: function () {
 8       return 3;
 9     }
10   };
11 
12   s1++;// 变成数值2
13   s2++;// 变成数值NaN
14   b--;// 变成数值0
15   f++;// 变成浮点数2.2
16   o--;// 变成数值2
17 }

一元加和减操作符

  一元加减操作符和我们在数学学的是完全一样的。一元加操作符放在数值前面,对数值是不会有任何影响的。但放在非数值前面时,操作符会像Number()转型函数一样对这个非数值执行转换。(Number转换函数的讲述可以参照http://www.cnblogs.com/xhni0/p/7461138.html)。与一元加操作符相似,都一元见操作符主要用于表示符号,在将一元减操作符应用于数值时,该值会变成负数。而当应用于非数值时,一元减操作符遵循与一元加操作符相同的规则,最后再将得到的数值转换为数值。

位操作符

  有了解过计算机组成原理的应该都不会不熟悉位操作符。位操作符用于在最基本的层次上,即按内存中表示数值的位来操作数值。ECMAScript中的所有数值都以IEEE-754 64位格式存储,但是位操作符并不直接操作64位的值。而是先将64位的值转换为32位的整数,然后执行操作,最后再将结果转换回64位。对于开发人员来说,由于64位存储格式是透明的,因此整个过程就像只存在32位的整数一样。

  对于有符号的整数,32位中的前31为用于表示整数的值。第32位用于表示数值的符号:0表示整数,1表示负数。这个表示符号的位叫做符号位。符号位的值决定了其他位数值的格式。

  正数以纯二进制格式存储,31位中的每一位都表示2的幂。第一位表示20,第二位表示21,以此类推。

  负数同样以二进制码存储,但使用的格式是二进制补码。二进制补码通过下列步骤获得,

  • 求这个数值绝对值的二进制码;
  • 求二进制码的反码;
  • 得到的二进制码加1;

  值得注意的事,对特殊的NaN和Infinity值应用位操作时,这两个值都会被当做0来处理。

按位非

  按位非操作符由一个波浪线(~)表示,执行按位非的结果就是返回数值的反码,在操作的本质上就是:操作数的负数减1.

按位与

  按位与操作符有一个和号字符(&)表示,它有两个操作数。在本质上讲,按位与操作就是将两个数值的每一位对齐,然后根据下表中的规则,对相同位置上的两个数执行AND操作。

第一个数值的位 第二个数值的位 结果
1 1 1
1 0 0
0 1 0
0 0 0

  按位与操作只在两个数值的对应位都是1时才返回1,任何一位是0,结果都是0。

按位或

  按位或操作符由一个竖线符号(|)表示,同样也有两个操作数。但遵循是如下的规则。

第一个数值的位 第二个数值的位 结果
1 1 1
1 0 1
0 1 1
0 0 0

  按位或操作在有一个位是1的情况下就返回1,而只有在两个位都是0的情况下才返回0。

按位异或

  按位异或操作符由一个插入符号(^)表示,也有两个操作符。真值表如下。

第一个数值的位 第二个数值的位 结果
1 1 0
1 0 1
0 1 1
0 0 0

  按位异或与按位或的不同之处在于,这个操作在两个数值对应位只有一个1时才返回1,如果对应位的两位都是1或都是0,则返回0。

左移

  左移操作符有两个小于号(<<)表示,这个操作符会将数值的所有位向左移动指定的位数。移位后的右侧空位用0来填充它们。左移操作不会影响操作数的符号位。

有符号右移

  有符号的右移操作符由两个大于号(>>)表示,这个操作符会将数值向右移动,但保留符号位,移位后的左侧空位用0来填充它们。有符号的右移操作符也不会影响操作数的符号位。

无符号右移

  无符号右移操作符由3个大于号(>>>)表示,这个操作符会将数值的所有32位都向右移动,对于正数来说,无符号右移的结果与有符号右移相同。

布尔操作符

  布尔操作符一共有3个:非、与和或。

逻辑非

  逻辑非操作符由一个叹号(!)表示,可以应用于任何的值,操作的结果都会返回一个布尔值。逻辑非操作首先会将它的操作数转换为一个布尔值,然后对其进行求反。具体规则如下,

  • 如果操作数是一个对象,返回false;
  • 如果操作数是一个空字符串,返回true;
  • 如果操作数是一个非空字符串,返回false;
  • 如果操作数是数值0,返回true;
  • 如果操作数是任何非0数值(包括Infinity),返回false;
  • 如果操作数是null,返回true;
  • 如果操作数是NaN,返回true;
  • 如果操作数是undefined,返回true;
1 {
2   console.log(!false);// true
3   console.log(!'blue');// false
4   console.log(!0);// true
5   console.log(!NaN);// true
6   console.log(!'');// true
7   console.log(!12345)// false
8 }

  逻辑非操作符也可以用于将一个值转换为与其对应的布尔值。而同时使用两个逻辑非操作符,实际上就会模拟Boolean()转型函数的行为。实际上,第一个逻辑非操作会基于无论什么操作数返回一个布尔值,而第二个逻辑非操作则对该布尔值求反,最终就得到了一个值的所对应的布尔值。

1 {
2   console.log(!!'blue');// true
3   console.log(!!0);// false
4   console.log(!!NaN);// false
5   console.log(!!'');// false
6   console.log(!!12345)// true
7 }

 逻辑与

  逻辑与操作符由两个和号(&&)表示,有两个操作数。真值表如下,

第一个操作数 第二个操作数 结果
true true true
true false false
false true false
false false false

   逻辑与操作可以应用于任何类型的操作数,而不仅仅是布尔值。在有一个操作数不是布尔值的情况下,逻辑与操作就不一定返回布尔值。而是遵循如下规则,

  • 如果第一个操作数是对象,则返回第二个操作数;
  • 如果第二个操作数是对象,则只有在第一个操作数的求值为true的情况下才能返回该对象;
  • 如果两个操作数都是对象,则返回第二个操作数;
  • 如果有一个操作数是null,则返回null;
  • 如果有一个操作数是NaN,则返回NaN;
  • 如果有一个操作数是undefined,则返回undefined。

  逻辑与操作属于短路操作,如果第一个操作数能够决定结果,那么就不会在对第二个求值。因为对于逻辑与操作而言,如果第一个操作数是false,那么无论第二个操作数是什么值,结果都不在可能是true了。这个特性在写代码时常常用于在变量有定义的情况下执行接下来的运算。

 1 {
 2   // 逻辑与的短路操作
 3   var boolTrue = true;
 4   var name1 = 'name1';
 5   console.log(boolTrue && name1)// name1
 6   var boolFalse = false;
 7   var name2 = 'name2';
 8   console.log(boolFalse && name2)// false
 9   // 逻辑与的短路操作的用法
10   var num1;
11   console.log(num1 && num1 + 3)// undefined,语句num+3因为num1的值为undeifned而不执行
12   num1 = 2;
13   console.log(num1 && num1 + 3)// 5
14 }

逻辑或

  逻辑或操作符由两个竖线(||)符号表示,有两个操作符,真值表如下

第一个操作数 第二个操作数 结果
true true true
true false true
false true true
false false false

  和逻辑与操作相似,如果有一个操作数不是布尔值,逻辑或也不一定返回布尔值,而是遵循如下规则,

  • 如果第一个操作数是对象,则返回第一个操作数;
  • 如果第一个操作数的求值结果为false,则返回第二个操作数;
  • 如果两个操作数都是对象,则返回第一个操作数;
  • 如果两个操作数都是null,则返回null;
  • 如果两个操作数都是NaN,则返回NaN;
  • 如果两个操作数都是undefined,则返回undefined;

  与逻辑与操作符相似,逻辑或操作符也是短路操作符。如果第一个操作数的求值结果为true,就不会对第二个操作数求值了。它的这个特征在代码时则常常用于函数变量的初始化赋值。

 1 {
 2   // 逻辑或的短路操作
 3   var boolTrue = true;
 4   var name1 = 'name1';
 5   console.log(boolTrue && name1)// true
 6   var boolFalse = false;
 7   var name2 = 'name2';
 8   console.log(boolFalse && name2)// name2
 9   // 逻辑或的短路操作的用法
10   function test (num1, num2) {
11     console.log(num1 || num1 = 2);
12     console.log(num2 || num2 = 2);
13   }
14   test(1)//传入num1变量都是不传入num2变量
15   // 输出的结果为 1  2
16   // num1有传入值,不执行num1 = 2的赋值语句
17   // num2无传入值,执行num2 = 2的赋值语句
18 }

乘性操作符

  乘性操作符有3个,乘法、除法和求模,这些操作符在操作数为非数值的情况下都会执行自动的类型转换。

乘法

  乘法操作符由一个星号(*)表示,用于计算两个数值的乘积。而在处理非数值时,乘法操作符遵循下列的规则。

  • 如果操作数都是数值,执行常规的乘法计算,即两个整数或者两个负数相乘的结果还是正数,而如果只有一个操作数有符号,那么结果就是负数。如果乘积超过了ECMAScript数值的表示范围,则返回Infinity或-Infinity;
  • 如果有一个操作数是NaN,则结果是NaN;
  • 如果是Infinity和0相乘,则结果是NaN;
  • 如果是Infinity与非0数值相乘,则结果是Infinity或-Infinity,取决于有符号操作数的符号;
  • 如果是Infinity和Infinity相乘,则结果是Infinity;
  • 如果有一个操作数不是数值,则在后台调用Number()将其转换为数值,然后再应用上面的规则;

除法

  除法操作符有一个斜线符号(/)表示,执行第二个操作数除第一个操作数的计算。和乘法操作符相似,除法操作符对非数值也会进行特殊的处理,规则如下。

  • 如果操作数都是数值,执行常规的除法计算。两个正数或两个负数相处的结果还是正数,而如果只有一个操作数有符号,那么结果就是负数。如果商超过了ECMAScript数值的表示范围,则返回Infinity或-Infinity;
  • 如果有一个操作数是NaN,则结果是NaN;
  • 如果是Infinity被Infinity除,则结果是NaN;
  • 如果是零被零除,则结果是NaN;
  • 如果是非零的有限数被零除,则结果是Infinity或-Infinity,取决于有符号操作数的符号;
  • 如果是Infinity被任何非零数值除,则结果是Infinity或-Infinity,取决于有符号操作数的符号;
  • 如果有一个操作数不是数值,则会调用Number()转换函数将其转换为数值,然后再应用上面的规则。

求模

  求模(余数)操作符由一个百分号(%)表示,运算规则如下。

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

加性操作符

  加性操作符包括加法和减法操作符两种。和乘性操作符相似,在运用于非数值时,加性操作符也会在后台进行特殊的数据类型转换。

加法

  加法操作符(+)的规则如下。

  • 如果两个操作数都是数值,执行常规的加法计算,然后根据下列规则返回结果,
    • 如果有一个操作数是NaN,则结果是NaN;
    • 如果是Infinity和Infinity,则结果是Infinity;
    • 如果是-Infinity和-Infinity,则结果是-Infinity;
    • 如果是Infinity和-Infinity, 则结果是NaN;
    • 如果是+0加+0,则结果是+0;
    • 如果是-0加-0,则结果是-0;
    • 如果是+0加-0,则结果是-0;
  • 如果有一个操作数是字符串,则根据下列规则运算,
    • 如果两个操作数都是字符串,则将第二个操作数与第一个操作数拼接起来;
    • 如果只有一个操作数是字符串,则将另一个操作数转换为字符串,然后再将两个字符串拼接起来。
  • 如果有一个操作数是对象、数值或布尔值,则调用它们的toString()方法取得相应的字符串值,然后再应用字符串的计算规则;
1 {
2   var num = 1 + 1;// 2
3   var str = 1 + '1';// '11'
4 }

 

减法

  减法操作符(-)的规则,

  • 如果是两个操作数都是数值,则执行常规的算术减法操作并返回结果;
  • 如果有一个操作数是NaN,则结果是NaN;
  • 如果是Infinity减Infinity,则结果是NaN;
  • 如果是-Infinity减-Infinity,则结果是NaN;
  • 如果是Infinity减-Infinity,则结果是Infinity;
  • 如果是-Infinity减Infinity,则结果是-Infinity;
  • 如果是+0减+0,则结果是+0;
  • 如果+0减-0,则结果是-0;
  • 如果是-0减-0,则结果是+0;
  • 如果有一个操作数是字符串、布尔值、null或undefined,则先调用Number()函数将其转换为数值,然后再根据前面的规则执行减法运算。如果转换的结果是NaN,则减法的结果就是NaN;
  • 如果有一个操作数是对象,则调用对象的valueOf()方法以取得表示该对象的数值。如果得到的值是NaN,则调用的结果就是NaN。如果对象没有valueOf()方法,则调用其toString()方法并将得到的字符串转换为数值;
1 {
2   var num1 = 5 - true;// 4,true转换为1
3   var num2 = NaN - 1;// NaN
4   var num3 = 5 - 3;// 2
5   var num4 = 5 - '';// 5,空字符串''被转换为0
6   var num5 = 5 - '2';// 3,'2'转换为2
7   var num6 = 5 - null;// 5,null转换为0
8 }

 

关系操作符

  关系操作符用于对两个值进行比较,返回一个布尔值true或false。比较的规则如下。

  • 如果两个操作数都是数值,则执行数值比较;
  • 如果两个操作数都是字符串,则比较两个字符串对象的字符串编码值;
  • 如果一个操作数是数值,则将另一个操作数转换为一个数值,然后执行数值比较;
  • 如果一个操作数是对象,则调用这个对象的valueOf()方法,用得到的结果按照前面的规则执行比较。如果对象没有valueOf()方法,则调用toString()方法,并用得到的结果根据前面的规则执行比较。
  • 如果一个操作数是布尔值。则先将其转换为数值,然后再执行比较;

相等操作符

  ECMAScript的相等操作符分两组,相等和不相等-----先转换在比较,全等和不全等-----仅比较而不转换。

相等和不相等

  相等操作符由两个等于号(==)表示,如果两个操作数相等,则返回true。而不相等操作符由叹号后跟等于号(!=)表示,如果两个操作数不相等,则返回true。这两个操作符都会先执行强制转换,然后再比较它们的相等性。

  在转换不同的数据类型时,相等和不相等操作符遵循如下规则。

  • 如果有一个操作数是布尔值,则在比较相等性之前先将其转换为数值-----false转换为0,而true转换为1;
  • 如果一个操作数是字符串,另一个操作数是数值,则在比较相等性之前先将字符串转换为数值;
  • 如果一个操作数是对象,另一个操作数不是,则调用对象的valueOf()方法,用得到的基本数据类型值按照前面的规则进行比较;

  这两个操作符在进行比较时同时还要遵循下面的规则,

  • null和undefined是相等的;
  • 要比较相等性之前,不能将null和undefined转换成其他任何值;
  • 如果有一个操作数是NaN,则相等操作符返回false,而不相等操作符返回true。;即使两个操作数都是NaN,相等操作符也返回false。因为NaN不等于NaN的规则存在。
  • 如果两个操作数都是对象,则比较他们是不是同一个对象。如果两个操作数都指向同一个对象,则相等操作符返回true,否则返回false;
 1 {
 2   null == undefined;// true
 3   'NaN' == NaN;// false
 4   5 == NaN;// false
 5   NaN == NaN;// false
 6   NaN != NaN;// true
 7   false == 0;// true
 8   true == 1;// true
 9   true == 2;// false
10   undefined == 0;// false
11   null == 0;// false
12   '5' == 5;// true
13 }

 

全等和不全等

  除了在比较之前不转换操作数之外,全等和不全等操作符没什么区别。全等操作符有3个等于号(===)表示,只有在两个操作数未经转换的相等的情况下返回true。而不全等操作符有一个叹号和两个等于号(!==)表示,它在两个操作数未经转换就相等的情况下返回true。

条件操作符

  条件操作符遵循如下语法形式,

    variable = boolean expression ? true_value :  false_value;

  这行代码的还以就是基于对boolean expression求值的结果,决定给变量variable赋什么值。如果求值结果为true,则给变量variable赋tru_value值;如果求值结果为false,则给变量variable赋false_value值。

1 {
2   var num1 = 1;
3   var num2 = 2;
4   var num3 = 5;
5   var num4 = num1 > num2 ?  (num3 + num1) :  (num3 + num2);//7
6 }

 

赋值操作符

  赋值操作符由等于号(=)表示,作用是把右侧的值赋给左侧的变量。而如果在等号前面在添加上乘性操作符、加性操作符或为操作符,就可以完成复合赋值操作。每一个主要算数操作符都有对象的复合赋值操作符,如下

  • 乘/赋值(*=);
  • 除/赋值(/=);
  • 模/赋值(%=);
  • 加/赋值(+=);
  • 减/赋值(-=);
  • 左移/赋值(<<=);
  • 有符号右移/赋值(>>=);
  • 无符号右移/赋值(>>>=);

逗号操作符

  逗号操作符用于一条语句执行多个操作的情况。

1 {
2   var num = 2, name = 'li', bool = true;
3 }

 

posted @ 2017-10-01 21:44  笛子Hardy  阅读(216)  评论(0编辑  收藏  举报