一元操作符
1. 递增和递减操作符 (++ –):
可以作用于任何类型的数据。对于这些类型,JavaScript会将他们转化为数值,再在这个数值上进行加一或减一操作。如果不能转化为一个数字,那么递增或递减的结果就是NaN
2. 加和减操作符 (= -):
既是一元操作符,也是二元操作符
(1)一元加运算符 (+)
一元加操作符会将其操作数转化为数值,并返回转化后的值。
- 操作数是数值,那它什么都不做;
- 操作数不能转化为数值,那么会返回NaN;
- BigInt值不能转化为数值,因此这个操作符不能用于BigInt。
let a = -1;
let b = "hello";
let c = BigInt;
console.log(+a) // -1
console.log(+b) // NaN
console.log(+c) // NaN
(2)一元减运算符(-)
一元减操作符会先将操作数转化为数值,然后会改变结果的符号
let a = -1;
let b = 2;
console.log(-a) // 1
console.log(-b) // -2
位操作符
计算机中数据都是以二进制的形式存储的(0,1两种状态)。计算机对二进制数据进行的运算加减乘除等都是叫位运算,即将符号位共同参与运算的运算。
运算符 | 描述 | 运算规则 |
---|---|---|
& | 与 | 两个位都为1时,结果才为1 |
| | 或 | 两个位都为0时,结果才为0 |
^ | 异或 | 两个位相同为0,相异为1 |
~ | 取反 | 0变1,1变0 |
<< | 左移 | 各二进制位全部左移若干位,高位丢弃,低位补0 |
>> | 右移 | 各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃 |
原码:一个数的二进制数
反码:正数的反码与原码相同;负数的反码为除符号位,按位取反(0变1,1变0)
原码:1000 1010
反码:1111 0101
补码:正数的补码与原码相同;负数的补码是原码除符号位外的所有位按位取反(0变1,1变0)然后加1(等于反码加1)
原码:1000 1010
反码:1111 0101
补码:1111 0110
1. 按位与操作符(&)
按位与操作符(&)会对参加运算的两个数据按二进制位进行与运算,即两位同时为 1 时,结果才为1,否则结果为0。运算规则如下:
0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1
例如,3 & 5 的运算结果如下:
0000 0011
0000 0101
= 0000 0001
因此 3 & 5 的值为 1。需要注意:负数按补码形式参加按位与运算。
用途:
(1)判断奇偶
只要根据最未位是0还是1来决定,为0就是偶数,为1就是奇数。因此可以用if ((i & 1) === 0)代替if (i % 2 === 0)来判断a是不是偶数。
(2)清零
如果想将一个单元清零,即使其全部二进制位为0,只要与一个各位都为零的数值相与,结果为零。
2. 按位或操作符(|)
负数按补码形式参加按位或运算。
例如,3 | 5 的运算结果如下:
0000 0011
0000 0101
= 0000 0111
因此,3 | 5的值为7。
3. 按位非操作符 (~)
例如:~6 的运算结果如下:
0000 0110
= 1111 1001
在计算机中,正数用原码表示,负数使用补码存储,首先看最高位,最高位1表示负数,0表示正数。此计算机二进制码为负数,最高位为符号位。
当按位取反为负数时,就直接取其补码,变为十进制:
0000 0110
= 1111 1001
反码:1000 0110
补码:1000 0111
因此,~6的值为-7。
按位非的操作结果实际上是对数值进行取反并减1,
4. 按位异或运算符(^)
5. 左移操作符(<<)
左移操作符(<<)会将运算对象的各二进制位全部左移若干位,左边的二进制位丢弃,右边补0。若左移时舍弃的高位不包含1,则每左移一位,相当于该数乘以2。
a =1010 1110
a = a << 2
!!!左移会保留他所操作数值的符号。比如,将-2左移5位,会得到-64,而不是64。
6. 右移运算符
(1)有符号右移操作符(>>)
有符号右移操作符(>>)会将数值的32位全部右移若干位(同时会保留正负号)。正数左补0,负数左补1,右边丢弃。操作数每右移一位,相当于该数除以2。
例如:a = a >>2 就是将a的二进制位右移2位,左补0 或者 左补1得看被移数是正还是负。
(2)无符号右移操作符(>>>)
无符号右移操作符(>>>)会将数值的32位全部右移。对于正数,有符号右移操作符和无符号右移操作符的结果是一样的。对于负数的操作,两者就会有较大的差异。
无符号右移操作符将负数的二进制表示当成正数的二进制表示来处理。所以,对负数进行无符号右移操作之后就会变的特别大。
加减乘除操作符
1. 加法操作符(+)
二元加操作符:用于**计算数值操作**或者**拼接字符串操作**。
在进行加操作时,如果两个操作数都是数值或者都是字符串,那么执行结果就分别是计算出来的数值和拼接好的字符串。
除此之外,执行结果都取决于类型转化的结果:
它会优先进行字符串拼接,只有操作数是字符串或者是可以转化为字符串的对象,另一个操作数也会被转化为字符串,并执行拼接操作。
只有任何操作数都不是字符串时才会执行加法操作。
1 + 2 // 3
"1" + "2" // "12"
"1" + 2 // "12"
1 + {} // "1[object Object]"
true + false // 1 布尔值会先转为数字,再进行运算
1 + null // 1 null会转化为0,再进行计算
1 + undefined // NaN undefined转化为数字是NaN
特殊情况:
- 一个操作数是NaN,结果是NaN;
- Infinity加Infinity,结果是Infinity;
- -Infinity加-Infinity,结果是-Infinity;
- Infinity加-Infinity,结果是NaN;
- +0加+0,结果是+0;
- -0加-0,结果是-0;
- +0加-0,结果是+0。
2. 减法操作符(-)
3 - 1 // 2
3 - true // 2
3 - "" // 3
3 - null // 3
NaN - 1 // NaN
特殊情况:
- Infinity减Infinity,结果是NaN;
- -Infinity减-Infinity,结果是NaN;
- Infinity减-Infinity,结果是Infinity;
- -Infinity减Infinity,结果是-Infinity;
- +0减+0,结果是+0;
- -0减+0,结果是-0;
- -0减-0,结果是+0。
3. 乘法操作符(*)
特殊情况:
- 有一个操作数是NaN,结果是NaN;
- Infinity与0相乘,结果是NaN;
- Infinity与非0数值相乘,结果是Infinity或-Infinity,取决于有符号操作数的符号;
- Infinity与Infinity相乘,则结果是Infinity。
4. 除法操作符(/)
特殊情况:
- 有一个操作数是NaN,结果是NaN;
- 0除以0,则结果是NaN;
- Infinity除以Infinity,结果是Infinity。
- 非零的有限数被零除,结果是Infinity或-Infinity,取决于有符号操作数的符号;
- Infinity被任何非零数值除,结果是Infinity或-Infinity,取决于有符号操作数的符号。
5. 取余操作符(%)
特殊情况:
- 被除数是无穷大值而除数是有限大的数值,结果是NaN;
- 被除数是有限大的数值而除数是零,结果是NaN;
- 是Infinity被Infinity除,结果是NaN;
- 被除数是有限大的数值而除数是无穷大的数值,结果是被除数;
- 被除数是零,结果是零。
6. 指数操作符(**)
以下两个计算效果是一样的:
Math.pow(2, 10); // 1024
2 ** 10; // 1024
布尔操作符
1. 逻辑非操作符(!)
可以用于js中的任何值,这个操作符使用返回布尔值,(首先会将操作数转化为布尔值,然后在对其取反。)
逻辑非操作规则如下:
- 如果操作数是对象,则返回 false;
- 如果操作数是空字符串,则返回 true;
- 如果操作数是非空字符串,则返回 false;
- 如果操作数是数值0,则返回 true;
- 如果操作数是非0数值(包括 Infinity),则返回 false;
- 如果操作数是 null,则返回 true;
- 如果操作数是 NaN,则返回 true;
- 如果操作数是 undefined, 则返回 true.
也可以用于将任何值转化为布尔值,同时使用两个!,相当于调用了Boolean()方法
2. 逻辑与操作符(&&)
两个操作数都为真,最终会返回真。
规则如下:
- 第一个操作符是对象, 返回 第二个操作符
- 第二个操作符是对象, 则 只有第一个操作数的求值结果为true的情况下才会返回该对象
- 两个操作数都是对象, 返回 第二个操作数
- 第一个操作数为null ,返回 null
- 第一个操作数为NaN, 返回 NaN
- 第一个操作数为 undefined, 返回 undefined
常用:
if(data) {
setData(data);
}
// 改写后:
data && setData(data);
3. 逻辑或操作符(||)
只要两个操作数中的一个为真,最终的结果就为真。该运算符可以用于任何类型的数据。如果有操作数不是布尔值,则结果并一定会返回布尔值。
规则如下:
- 第一个操作数是对象,则返回第一个操作对象;
- 第一个操作数的求值结果是false,则返回第二个操作数;
- 两个操作数都是对象,则返回第一个操作数;
- 两个操作数都是null,则返回null;
- 两个数都是NaN,则返回NaN;
- 两个数都是undefined,则返回undefined。
给变量设置默认值:let datas = data || {}
.逻辑非操作符
比较操作符
- 相等关系符
等于(== )
不等于( != )
全等( === )
不全等( !== ) - 关系操作符
小于(<)
大于(>)
小于等于(<=)
大于等于(>=) - 如果这两个操作数都是数值,则执行数值比较;
- 如果两个操作数都是字符串,则比较两个字符串对应的字符编码值;
- 如果一个操作数是数值,则将另一个操作数转换为一个数值,然后执行数值比较;
- 如果一个操作数是对象,则调用这个对象的valueOf()方法,并用得到的结果根据前面的规则执行比较;
- 如果一个操作数是布尔值,则先将其转换为数值,然后再执行比较。
其他操作符
开发常用,如下:
1. 扩展运算符
可以用来扩展一个数组对象和字符串。它用三个点(…)表示,可以将可迭代对象转为用逗号分隔的参数序列。
(1) 展开数组:
const a = [1, 2, 3],
b = [4, 5, 6];
const c = [...a] // [1, 2, 3]
const d = [...a, ...b] // [1, 2, 3, 4, 5, 6]
const e = [...a, 4, 5] // [1, 2, 3, 4, 5]
(2)类数组对象变数组:
const list = document.getElementsByTagName('a');
const arr = [...list]
(3)展开对象
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
const merged = { ...obj1, ...obj2 }; // { a: 1, b: 2, c: 3, d: 4 }
(4)展开字符串:
const str = "hello";
[...str] // ["h", "e", "l", "l", "o"]
(5)函数传参
const f = (foo, bar) => {}
const a = [1, 2]
f(...a)
const numbers = [1, 2, 3, 4, 5]
const sum = (a, b, c, d, e) => a + b + c + d + e
const sum = sum(...numbers)
2. 条件操作符(?😃 三目表达式
3. 赋值操作符
乘赋值操作符:*=
除赋值操作符:/=
模赋值操作符:%=
加赋值操作符:+=
减赋值操作符:-=
左移操作符: <<=
有符号右移赋值操作符:>>=
无符号右移赋值操作符:>>>=
4. in操作符
可以判断一个属性是否属于一个对象
还可以判断一个属性是否属于对象原型链的一部分
5. delete操作符
用于删除对象的某个属性或者数组元素。
!!!需要注意:
原型中声明的属性和对象自带的属性无法被删除;
通过var声明的变量和通过function声明的函数拥有dontdelete特性,是不能被删除。
6. instanceof操作符
instanceof运算符用来判断一个构造函数的prototype属性所指向的对象是否存在另外一个要检测对象的原型链上。instanceof运算符可以用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性。
```javascript
console.log([] instanceof Array); // true
console.log(function(){} instanceof Function); // true
console.log({} instanceof Object); // true
```
instanceof只能正确判断引用数据类型,而不能判断基本数据类型。
7. typeof操作符
x | typeof |
---|---|
null | object |
undefined | undefined |
true或false | boolean |
数值或NaN | number |
BigInt | bigInt |
字符串 | string |
symbol | symbol |
函数 | function |
非函数对象 | object |
8.空值合并操作符 (??)
在编写代码时,如果某个属性不为 null 和 undefined,那么就获取该属性,如果该属性为 null 或 undefined,则取一个默认值:
|| 使用有一定的缺陷,当为0或者false的时候,也走default
?? 只有左边为null和undefined的时候,走default
```javascript
const name = dogName ? dogName : ‘default’;
const name = dogName || 'default';
const dogName = false;
const name = dogName ?? 'default'; // name = false;
```
9. 可选链操作符 (?.)
在开发过程中,我们可能需要获取深层次属性,例如 system.user.addr.province.name。但在获取 name 这个属性前需要一步步的判断前面的属性是否存在,否则并会报错:
```javascript
a?.[x]
// 等同于
a == null ? undefined : a[x]
a?.b()
// 等同于
a == null ? undefined : a.b()
a?.()
// 等同于
a == null ? undefined : a()```
10. 逗号操作符(,)
声明多个变量的时候:
```javascript
let a = 1, b = 2, c = 3;
```
使用for循环的时候:
for(let i = 0, j = 10; i < j; i++, j--){
console.log(i + j);
}
11. void操作符(void)
void 是一元运算符,它可以出现在任意类型的操作数之前执行操作数,会忽略操作数的返回值,返回一个 undefined。void 常用于 HTML 脚本中执行 JavaScript 表达式,但不需要返回表达式的计算结果。
比如对于链接标签,我们并不想让它发生跳转,就可以设置href="javascript:void(0)
。
!!! void 运算符的优先级比较高,高于普通运算符的优先级,所以在使用时应该使用小括号明确 void 运算符操作的操作数