000003 - JavaScript语言基础(三)
1、操作符
在应用给对象时,操作符通常会调用valueOf()和/或toString()方法来取得可以计算的值。
1.1一元操作符
只操作一个值的操作符叫做一元操作符
01. 递增/递减操作符
前缀版就是位于要操作的变量前头,后缀版就是位于要操作的变量后头
无论使用前缀递增还是前缀递减操作符,变量的值都会在语句被求值之前改变;前缀递增和递减在语句中的优先级是相等的,因此会从左到右依次 求值
let age = 29;
let anotherAge = --age + 2;
console.log(age); // 28
console.log(anotherAge); // 30
let num2 = 20;
let num3 = --num1 + num2;
let num4 = num1 + num2;
console.log(num3); // 21
console.log(num4); // 21
后缀版递增和递减在语句被求值后才发生,把递增操作符放到变量后面不会改变语句执行的结果,因为递增是唯一的操作。可是,在跟其他操作混合时,差异就会变明显,比如:
let num1 = 2;
let num2 = 20;
let num3 = num1-- + num2;
let num4 = num1 + num2;
console.log(num3); // 22
console.log(num4); // 21
递增和递减操作符遵循如下规则。
- 对于字符串,如果是有效的数值形式,则转换为数值再应用改变。变量类型从字符串变成数值。
- 对于字符串,如果不是有效的数值形式,则将变量的值设置为NaN。变量类型从字符串变成数值。
- 对于布尔值,如果是false,则转换为0再应用改变。变量类型从布尔值变成数值。
- 对于布尔值,如果是true,则转换为1再应用改变。变量类型从布尔值变成数值。
- 对于浮点值,加1或减1。
- 如果是对象,则调用其(第5章会详细介绍的)valueOf()方法取得可以操作的值。对得到的值应用上述规则。如果是NaN,则调用toString()并再次应用其他规则。变量类型从对象变成数值
let s1 = "2";
let s2 = "z";
let b = false;
let f = 1.1;
let o = {
valueOf() {
return -1;
}
};
s1++; // 值变成数值3
s2++; // 值变成NaN
b++; // 值变成数值1
f--; // 值变成0.10000000000000009(因为浮点数不精确)
o--; // 值变成-2
02. 一元加和减
let s1 = "01";
let s2 = "1.1";
let s3 = "z";
let b = false;
let f = 1.1;
let o = {
valueOf() {
return -1;
}
};
s1 = +s1; // 值变成数值1
s2 = +s2; // 值变成数值1.1
s3 = +s3; // 值变成NaN
b = +b; // 值变成数值0
f = +f; // 不变,还是1.1
o = +o; // 值变成数值-1
let s1 = "01";
let s2 = "1.1";
let s3 = "z";
let b = false;
let f = 1.1;
let o = {
valueOf() {
return -1;
}
};
s1 = -s1; // 值变成数值-1
s2 = -s2; // 值变成数值-1.1
s3 = -s3; // 值变成NaN
b = -b; // 值变成数值0
f = -f; // 变成-1.1
o = -o; // 值变成数值1
1.2、位运算符
01.按位非
按位非操作符用波浪符(~)表示,它的作用是返回数值的一补数
let num1 = 25; // 二进制00000000000000000000000000011001
let num2 = ~num1; // 二进制11111111111111111111111111100110
console.log(num2); // -26
02. 按位与
按位与操作符用和号(&)表示,有两个操作数。本质上,按位与就是将两个数的每一个位对齐,然后基于真值表中的规则,对每一位执行相应的与操作
第一个数值的位 | 第二个数值的位 | 结果 |
---|---|---|
1 | 1 | 1 |
1 | 0 | 0 |
0 | 1 | 0 |
0 | 0 | 0 |
03. 按位或
按位或操作符用管道符(|)表示,同样有两个操作数。按位或遵循如下真值表
第一个数值的位 | 第二个数值的位 | 结果 |
---|---|---|
1 | 1 | 1 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
04. 按位异或
按位异或用脱字符(^)表示,同样有两个操作数。下面是按位异或的真值表:
第一个数的位 | 第二个数的位 | 结果 |
---|---|---|
1 | 1 | 0 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
05.左移
左移操作符用两个小于号(<<)表示,会按照指定的位数将数值的所有位向左移动。比如,如果数值2(二进制10)向左移5位,就会得到64(二进制1000000),如下所示:
let oldValue = 2; // 等于二进制10
let newValue = oldValue << 5; // 等于二进制1000000,即十进制64
06. 有符号右移
有符号右移由两个大于号(>>)表示,会将数值的所有32位都向右移,同时保留符号(正或负)。有符号右移实际上是左移的逆运算。比如,如果将64右移5位,那就是2:
let oldValue = 64; // 等于二进制1000000
let newValue = oldValue >> 5; // 等于二进制10,即十进制2
07. 无符号右移
无符号右移用3个大于号表示(>>>),会将数值的所有32位都向右移。对于正数,无符号右移与有符号右移结果相同。仍然以前面有符号右移的例子为例,64向右移动5位,会变成2:
let oldValue = 64; // 等于二进制1000000
let newValue = oldValue >>> 5; // 等于二进制10,即十进制2
1.3、布尔操作符
布尔操作符一共有3个:逻辑非、逻辑与和逻辑或
01. 逻辑非
逻辑非操作符由一个叹号(!)表示,可应用给ECMAScript中的任何值。这个操作符始终返回布尔值,无论应用到的是什么数据类型。逻辑非操作符首先将操作数转换为布尔值,然后再对其取反。换句话说,逻辑非操作符会遵循如下规则。
- 如果操作数是对象,则返回false。
- 如果操作数是空字符串,则返回true。
- 如果操作数是非空字符串,则返回false。
- 如果操作数是数值0,则返回true。
- 如果操作数是非0数值(包括Infinity),则返回false。
- 如果操作数是null,则返回true。
- 如果操作数是NaN,则返回true。
- 如果操作数是undefined,则返回true。
console.log(!false); // true
console.log(!"blue"); // false
console.log(!0); // true
console.log(!NaN); // true
console.log(!""); // true
console.log(!12345); // false
02. 逻辑与
逻辑与操作符由两个和号(&&)表示,应用到两个值,如下所示:
let result = true && false;
第一个操作数 | 第二个操作数 | 结果 |
---|---|---|
true | true | true |
true | false | false |
false | true | false |
false | false | false |
逻辑与操作符可用于任何类型的操作数,不限于布尔值。如果有操作数不是布尔值,则逻辑与并不一定会返回布尔值,而是遵循如下规则。
- 如果第一个操作数是对象,则返回第二个操作数。
- 如果第二个操作数是对象,则只有第一个操作数求值为true才会返回该对象。
- 如果两个操作数都是对象,则返回第二个操作数。
- 如果有一个操作数是null,则返回null。
- 如果有一个操作数是NaN,则返回NaN。
- 如果有一个操作数是undefined,则返回undefined。
03.逻辑或
逻辑或操作符由两个管道符(||)表示,比如:
let result = true || false;
第一个操作数 | 第二个操作数 | 结果 |
---|---|---|
true | true | true |
true | true | |
false | true | true |
false | false | false |
与逻辑与类似,如果有一个操作数不是布尔值,那么逻辑或操作符也不一定返回布尔值。它遵循如下规则。
- 如果第一个操作数是对象,则返回第一个操作数。
- 如果第一个操作数求值为false,则返回第二个操作数。
- 如果两个操作数都是对象,则返回第一个操作数。
- 如果两个操作数都是null,则返回null。
- 如果两个操作数都是NaN,则返回NaN。
- 如果两个操作数都是undefined,则返回undefined。
1.4、乘性操作符
ECMAScript定义了3个乘性操作符:乘法、除法和取模。如果乘性操作符有不是数值的操作数,则该操作数会在后台被使用Number()转型函数转换为数值。这意味着空字符串会被当成0,而布尔值true会被当成1。
01. 乘法操作符
乘法操作符由一个星号(*)表示,可以用于计算两个数值的乘积,乘法操作符在处理特殊值时有一些特殊的行为。
let result = 34 * 56;
- 如果操作数都是数值,则执行常规的乘法运算,即两个正值相乘是正值,两个负值相乘也是正值,正负符号不同的值相乘得到负值。如果ECMAScript不能表示乘积,则返回Infinity或-Infinity。
- 如果有任一操作数是NaN,则返回NaN。
- 如果是Infinity乘以0,则返回NaN。
- 如果是Infinity乘以非0的有限数值,则根据第二个操作数的符号返回Infinity或-Infinity。
- 如果是Infinity乘以Infinity,则返回Infinity。
- 如果有不是数值的操作数,则先在后台用Number()将其转换为数值,然后再应用上述规则。
02.除法操作符
除法操作符由一个斜杠(/)表示,用于计算第一个操作数除以第二个操作数的商除法操作符针对特殊值也有一些特殊的行为。
let result = 66 / 11;
- 如果操作数都是数值,则执行常规的除法运算,即两个正值相除是正值,两个负值相除也是正值,符号不同的值相除得到负 值。如果ECMAScript不能表示商,则返回Infinity或-Infinity。
- 如果有任一操作数是NaN,则返回NaN。
- 如果是Infinity除以Infinity,则返回NaN。
- 如果是0除以0,则返回NaN。
- 如果是非0的有限值除以0,则根据第一个操作数的符号返回Infinity或-Infinity。
- 如果是Infinity除以任何数值,则根据第二个操作数的符号返回Infinity或-Infinity。
- 如果有不是数值的操作数,则先在后台用Number()函数将其转换为数值,然后再应用上述规则。
03.取模操作符
取模(余数)操作符由一个百分比符号(%)表示
let result = 26 % 5; // 等于1
1.5、指数操作符
指数操作符,Math.pow()现在有了自己的操作符**,指数操作符也有自己的指数赋值操作符**=
console.log(Math.pow(3, 2); // 9
console.log(3 ** 2); // 9
console.log(Math.pow(16, 0.5); // 4
console.log(16** 0.5); // 4
let squared = 3;
squared **= 2;
console.log(squared); // 9
let sqrt = 16;
sqrt **= 0.5;
console.log(sqrt); // 4
1.6、 加性操作符
加性操作符,即加法和减法操作符,与乘性操作符类似,加性操作符在后台会发生不同数据类型的转换。
01.加法操作符
加法操作符(+)用于求两个数的和
let result = 1 + 2;
如果两个操作数都是数值,加法操作符执行加法运算并根据如下规则返回结果:
- 如果有任一操作数是NaN,则返回NaN;
- 如果是Infinity加Infinity,则返回Infinity;
- 如果是-Infinity加-Infinity,则返回-Infinity;
- 如果是Infinity加-Infinity,则返回NaN;
- 如果是+0加+0,则返回+0;
- 如果是-0加+0,则返回+0;
- 如果是-0加-0,则返回-0。
如果有一个操作数是字符串,则要应用如下规则:
- 如果两个操作数都是字符串,则将第二个字符串拼接到第一个字符串后面;
- 如果只有一个操作数是字符串,则将另一个操作数转换为字符串,再将两个字符串拼接在一起。
02.减法操作符
与加法操作符一样,减法操作符也有一组规则用于处理ECMAScript中不同类型之间的转换
- 如果两个操作数都是数值,则执行数学减法运算并返回结果。
- 如果有任一操作数是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()方法,然后再将得到的字符串转换为数值。
let result1 = 5 - true; // true被转换为1,所以结果是4
let result2 = NaN - 1; // NaN
let result3 = 5 - 3; // 2
let result4 = 5 - ""; // ""被转换为0,所以结果是5
let result5 = 5 - "2"; // "2"被转换为2,所以结果是3
let result6 = 5 - null; // null被转换为0,所以结果是5
1.7、关系操作符
关系操作符执行比较两个值的操作,包括小于(<)、大于(>)、小于等于(<=)和大于等于(>=),用法跟数学课上学的一样,符都返回布尔值,在将它们应用到不同数据类型时也会发生类型转换和其他行为。
-
如果操作数都是数值,则执行数值比较。如果操作数都是字符串,则逐个比较字符串中对应字符的编码。
-
如果有任一操作数是数值,则将另一个操作数转换为数值,执行数值比较。
-
如果有任一操作数是对象,则调用其valueOf()方法,取得结果后再根据前面的规则执行比较。如果没有valueOf()操作符,则调用toString()方法,取得结果后再根据前面的规则执行比较。
-
如果有任一操作数是布尔值,则将其转换为数值再执行比较。
let result1 = 5 > 3; // true let result2 = 5 < 3; // false let result = "Brick" < "alphabet"; // true let result = "Brick".toLowerCase() < "alphabet".toLowerCase(); // false let result = "23" < "3"; // true let result = "a" < 3; // 因为"a"会转换为NaN,所以结果是false
任何关系操作符在涉及比较NaN时都返回false
let result1 = NaN < 3; // false
let result2 = NaN >= 3; // false
1.8、 相等操作符
01.等于和不等于
ECMAScript中的等于操作符用两个等于号(==)表示,如果操作数相等,则会返回true。不等于操作符用叹号和等于号(!=)表 示,如果两个操作数不相等,则会返回true。这两个操作符都会先进行类型转换(通常称为强制类型转换)再确定操作数是否相等。
在转换操作数的类型时,相等和不相等操作符遵循如下规则。
- 如果任一操作数是布尔值,则将其转换为数值再比较是否相等。false转换为0,true转换为1。
- 如果一个操作数是字符串,另一个操作数是数值,则尝试将字符串转换为数值,再比较是否相等。
- 如果一个操作数是对象,另一个操作数不是,则调用对象的valueOf()方法取得其原始值,再根据前面的规则进行比较
在进行比较时,这两个操作符会遵循如下规则。
- null和undefined相等。
- null和undefined不能转换为其他类型的值再进行比较。
- 如果有任一操作数是NaN,则相等操作符返回false,不相等操作符返回true。记住:即使两个操作数都是NaN,相等操作符也返回false,因为按照规则,NaN不等于NaN。
- 如果两个操作数都是对象,则比较它们是不是同一个对象。如果两个操作数都指向同一个对象,则相等操作符返回true。否则,两者不相等
表达式 | 结果 |
---|---|
null == undefined | true |
“NaN” == NaN | false |
5 == NaN | false |
NaN == NaN | false |
NaN != NaN | true |
false == 0 | true |
true == 1 | true |
true == 2 | false |
undefined == 0 | false |
null == 0 | false |
“5” == 5 | true |
02. 全等和不全等
全等和不全等操作符与相等和不相等操作符类似,只不过它们在比较相等时不转换操作数。全等操作符由3个等于号(===)表示,只有两个操作数在不转换的前提下相等才返回true
let result1 = ("55" == 55); // true,转换后相等
let result2 = ("55" === 55); // false,不相等,因为数据类型不同
不全等操作符用一个叹号和两个等于号(!==)表示,只有两个操作数在不转换的前提下不相等才返回true
let result1 = ("55" != 55); // false,转换后相等
let result2 = ("55" !== 55); // true,不相等,因为数据类型不同
1.9、条件操作符
variable = boolean_expression ? true_value : false_value;
let max = (num1 > num2) ? num1 : num2;
1.10、赋值操作符
let num = 10;
num = num + 10;
1.11、逗号操作符
逗号操作符可以用来在一条语句中执行多个操作
let num1 = 1, num2 = 2, num3 = 3;
let num = (5, 1, 4, 8, 0); // num的值为0