您的位置:首页 > Web前端 > JavaScript

JavaScript 操作符全解析

2017-02-08 15:19 204 查看
——跟我一起学 JavaScript (6)

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 操作,规则如下:

第一个数的位第二个数的位结果
111
100
010
000
即按位与操作中,只有两个数值对应的位都是 1 时,才返回 1。

<!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 按位或

由 | 表示,规则如下:

第一个数的位第二个数的位结果
111
101
011
000
即按位或操作中,只有两个数值对应的位都是 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 按位异或

由插入符号 ^ 表示,规则如下:

第一个数的位第二个数的位结果
110
101
011
000
只有两个数值对应的位只有一个 1 时,才返回 1。

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
0true
非 0 数值(包括 Infinity)false
nulltrue
NaNtrue
undefinedtrue
<!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 逻辑与

由 && 表示,规则如下:

第一个操作数第二个操作数结果
truetruetrue
truefalsefalse
falsetruefalse
falsefalsefalse
可以应用于任何类型的操作数。

如果有一个操作数不是布尔值,就不一定返回布尔值,具体规则:

操作数类型结果
第一个操作数是对象返回第二个操作数
第二个操作数是对象只有第一个操作数求值结果为 true,才会返回该对象
两个操作数都是对象返回第二个操作数
有一个操作数是 nullnull
有一个操作数是 NaNNaN
有一个操作数是 undefinedundefined
逻辑与操作属于短路操作,即如果第一个操作数能够决定结果,就不会再对第二个操作数执行求值。

<!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 逻辑或

由 || 表示,规则如下:

第一个操作数第二个操作数结果
truetruetrue
truefalsetrue
falsetruetrue
falsefalsefalse
与逻辑与相似,如果有一个操作数不是布尔值,逻辑或就不一定返回布尔值,具体规则:

操作数类型结果
第一个操作数是对象返回第一个操作数
第一个操作数是求值结果为 false返回第二个操作数
两个操作数都是对象返回第一个操作数
有一个操作数是 nullnull
有一个操作数是 NaNNaN
有一个操作数是 undefinedundefined
逻辑或操作也属于短路操作,即如果第一个操作数的求值结果为 true,就不会再对第二个操作数执行求值。

<!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
有一个操作数是 NaNNaN
Infinity 与 0 相乘NaN
Infinity 与 非 0 数值相乘Infinity
Infinity 与 Infinity 相乘Infinity
有一个操作数不是数值后台调用 Number() 转换为数值,在应用上面的规则

4.2 除法

由斜线(/)表示,具体规则:

操作数类型结果
都是数值常规除法运算,如果商超过表示范围,则返回 Infinity
有一个操作数是 NaNNaN
Infinity 被 Infinity 除NaN
0 被 0 除NaN
非零的有限数被 0 除Infinity
Infinity 与 非 0 数值除Infinity
有一个操作数不是数值后台调用 Number() 转换为数值,再应用上面的规则

5 加性操作符

5.1 加法

操作数类型结果
有一个操作数是 NaNNaN
Infinity 加 InfinityInfinity
-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 减法

操作数类型结果
两个操作数都是数值常规减法
有一个操作数是 NaNNaN
Infinity 减 InfinityNaN
-Infinity 减 -Infinity-Infinity
Infinity 减 -InfinityInfinity
-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;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: