JavaScript 操作符全解析
2017-02-08 15:19
204 查看
——跟我一起学 JavaScript (6)
ECMAScript 操作符能够适应多种类型的值。
应用于对象时,相应的操作符会调用对象的 valueOf() 或 toString() 方法,以取得可以操作的值。
前置递增或递减时,变量的值都是在语句被求值以前改变的,称为副效应:
由于前置递增和递减操作与执行语句的优先级相等,因此整个语句会从左到右被求值:
后置型的递增和递减操作会在包含的语句被求值后才执行:
规则如下:
对非数值应用一元加操作符,会像调用 Number() 转型函数一样对这个值执行转换:
一元减操作符用于表示负数。
对非数值应用一元减操作符时,也会遵循与一元加操作符相同的规则,最后再把数值转换为负数:
一元加和减操作符主要用于算术运算,也可用于数据类型的转换。
ECMAScript 中所有的数值都是以 IEEE-754 64 位格式存储,但位操作符会先将 64 位的值转换为 32 位的整数,然后执行操作,最后再将结果转换为 64 位。这会导致严重的副效应,即对 NaN 和 Infinity 值应用位操作时,会被当做 0 来处理。
对于有符号整数,第 32 位表示数值的符号;0 表示正数,1 表示负数。
负数使用的格式是二进制补码。
计算二进制补码的步骤:
1. 求数值绝对值的二进制码
2. 求二进制反码
3. 将二进制反码加 1
ECMAScript 会隐藏上面的信息,以二进制字符串形式输出负数时,只会在这个负数绝对值的二进制码前加一个负号:
默认情况下,ECMAScript 中所有整数都是有符号整数。
如果对非数值应用位操作符,会先自动使用 Number() 函数将该值转换为数值,再进行下一步操作。
即按位与操作中,只有两个数值对应的位都是 1 时,才返回 1。
即按位或操作中,只有两个数值对应的位都是 0 时,才返回 0。
只有两个数值对应的位只有一个 1 时,才返回 1。
左移后多出的空位会以 0 来填充。
左移不会影响操作数的符号位。
负数是以其绝对值额二进制补码形式表示,所以对负数执行无符号右移后,结果会变得非常大。
同时使用两个逻辑非操作符,实际上就会模拟出 Boolean() 函数的行为:
可以应用于任何类型的操作数。
如果有一个操作数不是布尔值,就不一定返回布尔值,具体规则:
逻辑与操作属于短路操作,即如果第一个操作数能够决定结果,就不会再对第二个操作数执行求值。
与逻辑与相似,如果有一个操作数不是布尔值,逻辑或就不一定返回布尔值,具体规则:
逻辑或操作也属于短路操作,即如果第一个操作数的求值结果为 true,就不会再对第二个操作数执行求值。
可以利用逻辑或的这一行为来避免为变量赋值 null 或 undefined 值:
backupObject 可以在 preferredObejct 不包含有效值的情况下提供备用值。
程序的赋值语句经常会采用这样的模式。
忽视加法操作中的数据类型,是编程的常见错误(使用圆括号可以避免):
注意:
用关系操作符比较两个字符串时,比较的是两个字符串中对应位置的每个字符的字符编码值。因此,如果要真正按字母表顺序比较字符串,就必须把两个操作数都转换为相同的大小写形式后,再进行比较。
比较数值的字符串形式时,比较的也是字符串编码。
任何操作数与NaN 比较,结果都是 false。
比较规则:
null 和 undefined 是相等的。
比较相等性之前,不能将 null 和 undefined 转换成其他任何值。
有一个操作数是 NaN,则相等操作符返回 false;即使两个操作数都是 NaN,相等操作符也是返回 false(因为 NaN 不等于 NaN)。
如果两个操作数都是对象,则比较它们是不是同一个对象(即指向同一个对象)。
注意:
null == undefined ,返回 true。
null === undefined,返回 false。
为了保证代码中数据类型的完整性,推荐使用全等和不全等操作符。
用于简化代码的编写
每个主要的算法操作符都有对应的复合赋值操作符。
只是简化代码,不会带来性能的提升。
ECMAScript 操作符能够适应多种类型的值。
应用于对象时,相应的操作符会调用对象的 valueOf() 或 toString() 方法,以取得可以操作的值。
1 一元操作符
只能操作一个值1.1 递增与递减操作符
分为前置和后置两种情况前置递增或递减时,变量的值都是在语句被求值以前改变的,称为副效应:
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>前置递增与递减的副效应</title> </head> <body> <script type="text/javascript"> var age = 19; var anotherAge = --age + 2; console.log(age);//18 console.log(anotherAge);//20 </script> </body> </html>
由于前置递增和递减操作与执行语句的优先级相等,因此整个语句会从左到右被求值:
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>前置递增与递减与执行语句的优先级相等</title> </head> <body> <script type="text/javascript"> var num1 = 2; var num2 = 20; console.log(--num1 + num2);//21 console.log(num1 + num2);//21 </script> </body> </html>
后置型的递增和递减操作会在包含的语句被求值后才执行:
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>后置递增与递减在包含它们的语句求值后才执行</title> </head> <body> <script type="text/javascript"> var num1 = 2; var num2 = 20; console.log(num1-- + num2);//22 console.log(num1 + num2);//21 </script> </body> </html>
规则如下:
应用的对象 | 操作 |
---|---|
包含有效数字字符 | 转换为数字值,再执行 |
不包含有效数字字符 | NaN |
false | 转换为0,再执行 |
true | 转换为1,再执行 |
浮点数值 | 执行 |
对象 | 先调用对象的 valueOf() 方法取得值,然后应用上述规则;如果结果是 NaN,再调用 toString() 方法取得值,然后应用上述规则 |
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>后置递增与递减操作符规则</title> </head> <body> <script type="text/javascript"> var s1 = "2"; var s2 = "z"; var b = false; var f = 1.1; var o = { valueOf: function () { return -1; } }; s1++; //3 s2++;//NaN b++;//1 f--;//0.10000000000000009(浮点舍入错误) o--;//-2 </script> </body> </html>
1.2 一元加和减操作符
一元加操作符放在数值前面,对数值不会产生影响。对非数值应用一元加操作符,会像调用 Number() 转型函数一样对这个值执行转换:
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>不同数据类型应用一元操作符类型</title> </head> <body> <script type="text/javascript"> var s1 = "01"; var s2 = "1.1"; var s3 = "z"; var b = false; var f = 1.1; var o = { valueOf: function () { return -1; } }; s1 = +s1;//1 s2 = +s2;//1.1 s3 = +s3;//NaN b = +b;//0 f = +f;//1.1 o = +o;//-1 </script> </body> </html>
一元减操作符用于表示负数。
对非数值应用一元减操作符时,也会遵循与一元加操作符相同的规则,最后再把数值转换为负数:
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>一元减操作符应用于数值时,该值会变为负数</title> </head> <body> <script type="text/javascript"> var s1 = "01"; var s2 = "1.1"; var s3 = "z"; var b = false; var f = 1.1; var o = { valueOf: function () { return -1; } }; s1 = -s1;//-1 s2 = -s2;//-1.1 s3 = -s3;//NaN b = -b;//0(Chrome 中会变为 -0) f = -f;//-1.1 o = -o;//1 </script> </body> </html>
一元加和减操作符主要用于算术运算,也可用于数据类型的转换。
2 位操作符
位操作符会按内存中表示数值的位来操作数值。ECMAScript 中所有的数值都是以 IEEE-754 64 位格式存储,但位操作符会先将 64 位的值转换为 32 位的整数,然后执行操作,最后再将结果转换为 64 位。这会导致严重的副效应,即对 NaN 和 Infinity 值应用位操作时,会被当做 0 来处理。
对于有符号整数,第 32 位表示数值的符号;0 表示正数,1 表示负数。
负数使用的格式是二进制补码。
计算二进制补码的步骤:
1. 求数值绝对值的二进制码
2. 求二进制反码
3. 将二进制反码加 1
ECMAScript 会隐藏上面的信息,以二进制字符串形式输出负数时,只会在这个负数绝对值的二进制码前加一个负号:
var num = -18; alert(num.toString(2)); //"-10010"
默认情况下,ECMAScript 中所有整数都是有符号整数。
如果对非数值应用位操作符,会先自动使用 Number() 函数将该值转换为数值,再进行下一步操作。
2.1 按位非
由波浪线(~)表示,返回数值的反码:<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>按位非</title> </head> <body> <script type="text/javascript"> var num1 = 25; var num2 = ~num1; console.log(num2);//-26 </script> </body> </html>
2.2 按位与
由 & 表示,对相同位置上的两个数执行 AND 操作,规则如下:第一个数的位 | 第二个数的位 | 结果 |
---|---|---|
1 | 1 | 1 |
1 | 0 | 0 |
0 | 1 | 0 |
0 | 0 | 0 |
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>按位与</title> </head> <body> <script type="text/javascript"> var result = 25 & 3; console.log(result);//1 </script> </body> </html>
2.3 按位或
由 | 表示,规则如下:第一个数的位 | 第二个数的位 | 结果 |
---|---|---|
1 | 1 | 1 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>按位或</title> </head> <body> <script type="text/javascript"> var result = 25 | 3; console.log(result);//27 </script> </body> </html>
2.4 按位异或
由插入符号 ^ 表示,规则如下:第一个数的位 | 第二个数的位 | 结果 |
---|---|---|
1 | 1 | 0 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
2.5 左移
由两个小于号(<<)表示,会将数值中的所有位向左移动指定的位数。左移后多出的空位会以 0 来填充。
左移不会影响操作数的符号位。
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>左移</title> </head> <body> <script type="text/javascript"> var oldValue = 2; console.log(oldValue << 5);//64 </script> </body> </html>
2.6 有符号的右移
由两个大于号(>>)表示,会将数值中的除了符号位之外的所有位向右移动指定的位数:<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>有符号右移</title> </head> <body> <script type="text/javascript"> var oldValue = 64; console.log(oldValue >> 5);//2 </script> </body> </html>
2.7 无符号右移
由三个大于号(>>>)表示,会将数值中的所有位向右移动指定的位数:<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>无符号右移</title> </head> <body> <script type="text/javascript"> var oldValue = 64; console.log(oldValue >>> 5);//2 </script> </body> </html>
负数是以其绝对值额二进制补码形式表示,所以对负数执行无符号右移后,结果会变得非常大。
3 布尔操作符
3.1 逻辑非
由 ! 表示,可以应用于任何 ECMAScript 类型。规则如下:操作数 | 结果 |
---|---|
对象 | false |
空字符串 | true |
非空字符串 | false |
0 | true |
非 0 数值(包括 Infinity) | false |
null | true |
NaN | true |
undefined | true |
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>逻辑非</title> </head> <body> <script type="text/javascript"> console.log(!false);//true console.log(!"blue");//false console.log(!0);//true console.log(!NaN);//true console.log(!"");//true console.log(!12345);//false </script> </body> </html>
同时使用两个逻辑非操作符,实际上就会模拟出 Boolean() 函数的行为:
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>两个逻辑非可以模拟出一个 Boolean 函数</title> </head> <body> <script type="text/javascript"> console.log(!!"blue");//true console.log(!!0);//false console.log(!!NaN);//false console.log(!!"");//false console.log(!!12345);//true </script> </body> </html>
3.2 逻辑与
由 && 表示,规则如下:第一个操作数 | 第二个操作数 | 结果 |
---|---|---|
true | true | true |
true | false | false |
false | true | false |
false | false | false |
如果有一个操作数不是布尔值,就不一定返回布尔值,具体规则:
操作数类型 | 结果 |
---|---|
第一个操作数是对象 | 返回第二个操作数 |
第二个操作数是对象 | 只有第一个操作数求值结果为 true,才会返回该对象 |
两个操作数都是对象 | 返回第二个操作数 |
有一个操作数是 null | null |
有一个操作数是 NaN | NaN |
有一个操作数是 undefined | undefined |
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>逻辑与操作</title> </head> <body> <script type="text/javascript"> var found = true; var result = (found && someUnderfinedVariable); //报错 console.log(result);//不会执行 </script> </body> </html> <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>逻辑与操作(短路操作)</title> </head> <body> <script type="text/javascript"> var found = false; var result = (found && someUnderfinedVariable); //不会报错 console.log(result);//会执行 </script> </body> </html>
3.3 逻辑或
由 || 表示,规则如下:第一个操作数 | 第二个操作数 | 结果 |
---|---|---|
true | true | true |
true | false | true |
false | true | true |
false | false | false |
操作数类型 | 结果 |
---|---|
第一个操作数是对象 | 返回第一个操作数 |
第一个操作数是求值结果为 false | 返回第二个操作数 |
两个操作数都是对象 | 返回第一个操作数 |
有一个操作数是 null | null |
有一个操作数是 NaN | NaN |
有一个操作数是 undefined | undefined |
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>逻辑或(短路操作)</title> </head> <body> <script type="text/javascript"> var found = true; var result = (found || someUnderfinedVariable); //不会报错 console.log(result);//不执行 </script> </body> </html>
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>逻辑与操作(短路操作)</title> </head> <body> <script type="text/javascript"> var found = false; var result = (found && someUnderfinedVariable); //不会报错 console.log(result);//会执行 </script> </body> </html>
可以利用逻辑或的这一行为来避免为变量赋值 null 或 undefined 值:
var myObject = preferredObejct || backupObject;
backupObject 可以在 preferredObejct 不包含有效值的情况下提供备用值。
程序的赋值语句经常会采用这样的模式。
4 乘性操作符
操作数如果是非数值,会自动执行类型转换。4.1 乘法
由星号(*)表示,具体规则:操作数类型 | 结果 |
---|---|
都是数值 | 常规乘法运算,如果乘积超过表示范围,则返回 Infinity |
有一个操作数是 NaN | NaN |
Infinity 与 0 相乘 | NaN |
Infinity 与 非 0 数值相乘 | Infinity |
Infinity 与 Infinity 相乘 | Infinity |
有一个操作数不是数值 | 后台调用 Number() 转换为数值,在应用上面的规则 |
4.2 除法
由斜线(/)表示,具体规则:操作数类型 | 结果 |
---|---|
都是数值 | 常规除法运算,如果商超过表示范围,则返回 Infinity |
有一个操作数是 NaN | NaN |
Infinity 被 Infinity 除 | NaN |
0 被 0 除 | NaN |
非零的有限数被 0 除 | Infinity |
Infinity 与 非 0 数值除 | Infinity |
有一个操作数不是数值 | 后台调用 Number() 转换为数值,再应用上面的规则 |
5 加性操作符
5.1 加法
操作数类型 | 结果 |
---|---|
有一个操作数是 NaN | NaN |
Infinity 加 Infinity | Infinity |
-Infinity 加 -Infinity | -Infinity |
+0 加 +0 | +0 |
-0 加 -0 | -0 |
+0 加 -0 | +0 |
两个操作数都是字符串 | 第二个与第一个拼接 |
只有一个操作数是字符串 | 另一个字符串转换为字符串,再拼接 |
有一个操作数是对象、数值或布尔值 | 调用它的 toString() 方法取得字符串值,再按照字符串规则处理;对于nudefined 和 null,则调用 String() 取得 “undefined” 和 “null” |
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>加法</title> </head> <body> <script type="text/javascript"> console.log(5+5);//10 console.log(5+"5");//55 </script> </body> </html>
忽视加法操作中的数据类型,是编程的常见错误(使用圆括号可以避免):
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>加法使用的常见错误</title> </head> <body> <script type="text/javascript"> var num1 = 5; var num2 = 10; console.log("The sum of 5 and 10 is " + num1 + num2);//510 console.log("The sum of 5 and 10 is " + (num1 + num2));//15 </script> </body> </html>
5.2 减法
操作数类型 | 结果 |
---|---|
两个操作数都是数值 | 常规减法 |
有一个操作数是 NaN | NaN |
Infinity 减 Infinity | NaN |
-Infinity 减 -Infinity | -Infinity |
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() 并将得到的字符串转换为数值 |
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>减法操作</title> </head> <body> <script type="text/javascript"> console.log(5 - true);//4;true 被转换为 1 console.log(NaN -1);//NaN console.log(5 - 3);//2 console.log(5 - "");//5;"" 被转换为 0 console.log(5 - "2");//3 console.log(5 - null);//5;null 被转换为 0 </script> </body> </html>
6 关系操作符
当关系操作符使用了非数值时,就会进行数值转换,规则:操作数类型 | 结果 |
---|---|
两个操作数都是数值 | 数值比较 |
两个操作数都是字符串 | 比较两个字符串中对应的字符编码值 |
有一个操作数是数值 | 另一个操作数转换为数值,再比较 |
有一个操作数是对象 | 调用对象的 valueOf() ,再按照前面的规则执行比较;如果对象没有 valueOf() 方法,则调用 toString() 并将得到的结果进行比较 |
有一个操作数是布尔值 | 先转换为数值,再比较 |
用关系操作符比较两个字符串时,比较的是两个字符串中对应位置的每个字符的字符编码值。因此,如果要真正按字母表顺序比较字符串,就必须把两个操作数都转换为相同的大小写形式后,再进行比较。
比较数值的字符串形式时,比较的也是字符串编码。
任何操作数与NaN 比较,结果都是 false。
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>关系操作符</title> </head> <body> <script type="text/javascript"> console.log(5 > 3);//true console.log(5 < 3);//false //字符串比较的是字符串中对应位置的字符编码值,而大写字母的编码值都小于小写字母的字符编码 console.log("Brick" < "alphabet");//true console.log("Brick".toLowerCase() < "alphabet".toLowerCase());//false;全部转为小写或者大写,这样就能按照字母表顺序比较 console.log("23" < "3");//true;数字字符串比较的还是字符编码 console.log("23" < 3);//false;其中一个操作数如果是数字,就会把另一个操作数也转为数字后,再进行比较 console.log("a" < 3);//false;非法数字的字符串会被转换为 NaN,任何操作数与 NaN 比较都是 false。 console.log(NaN < 3);//false console.log(NaN >= 3);//false </script> </body> </html>
7 相等操作符
7.1 相等(==)与不相等(!=)
会先转换(强制转换),再比较;转换规则:操作数类型 | 结果 |
---|---|
有一个操作数是布尔值 | 先转换为数值;false 转为 0,true 转为 1 |
一个操作数是字符串,另一个是数值 | 先将字符串转换为数值,再比较 |
一个操作数是对象,另一个不是 | 调用对象的 valueOf() 方法,再比较 |
null 和 undefined 是相等的。
比较相等性之前,不能将 null 和 undefined 转换成其他任何值。
有一个操作数是 NaN,则相等操作符返回 false;即使两个操作数都是 NaN,相等操作符也是返回 false(因为 NaN 不等于 NaN)。
如果两个操作数都是对象,则比较它们是不是同一个对象(即指向同一个对象)。
7.2 全等(===)与不全等
比较前不会自动转换:<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>相等操作符</title> </head> <body> <script type="text/javascript"> //全等和不全等与相等和不相等的唯一区别就是,在比较前不转换操作符 console.log("55" == 55);//true console.log("55" === 55);//false console.log("55" != 55);//false console.log("55" !== 55);//true </script> </body> </html>
注意:
null == undefined ,返回 true。
null === undefined,返回 false。
为了保证代码中数据类型的完整性,推荐使用全等和不全等操作符。
8 条件操作符
variable = boolean_expression ? true_value : false_value;
用于简化代码的编写
9 赋值操作符
赋值操作符是常规表达式的简化写法。每个主要的算法操作符都有对应的复合赋值操作符。
只是简化代码,不会带来性能的提升。
10 逗号操作符
可以在一条语句中执行多个操作,多用于声明多个变量:var num=1, num2=2, num3=3;
相关文章推荐
- 解析JavaScript中delete操作符不能删除的对象
- 全面解析JavaScript中“&&”和“||”操作符(总结篇)
- javascript数组之in操作符在各个浏览器解析的差异
- JavaScript typeof操作符以及其它一些小测试题目解析
- 全面解析JavaScript中“&&”和“||”操作符(总结篇)
- 全面解析JavaScript中“&&”和“||”操作符
- 解析JavaScript中delete操作符不能删除的对象
- 全面解析JavaScript中“&&”和“||”操作符(总结篇)
- 全面解析JavaScript中“&&”和“||”操作符(总结篇)
- 解析JavaScript中delete操作符不能删除的对象
- 全面解析JavaScript中“&&”和“||”操作符(总结篇)
- JavaScript中的正则表达式解析
- javascript生成/解析dom的CDATA类型的字段的代码
- javaScript 中的正则表达式解析
- 关于JavaScript的“+”运算和“-”运算和三目操作符“?:”
- javascript event 事件解析
- [JS]详尽解析window.event对象 --javascript 教程及特效
- 解析arp病毒背后利用的Javascript技术附解密方法
- 详尽解析event对象(javascript)
- curl 转译url地址为unicode码并前台javascript解析