运算符(operator)也被称为操作符,是用于实现赋值、比较和执行计算数运算等 功能的符号
常用的运算符有: 算数运算符、递增和递减运算符、比较运算符、逻辑运算符、赋值运算符
1. 算数运算符
1.1 概述:算术运算使用的符号,用于执行两个变量或值的算术运算
+:加10 + 20 = 30-: 减10 -20 = -10*: 乘10 * 20 = 200/: 除10 / 20 = 0.5%: 取余数(取模)9 % 2 = 1返回除法的余数
1.2 浮点数的精度问题
- 浮点数值的最高精度是17位小数,但是在运行算术时其精度远远不如整数
// 浮点数 算数运算里面会有问题
console.log(0.1 + 0.2); //0.30000000000000004
console.log(0.07 * 100);//7.000000000000001
- 不要直接判断两个浮点数是否相等
var num = 0.1 + 0.2
console.log(num == 0.3) // false
1.3 表达式和返回值
- 表达式:是由数字、运算符、变量等以能求得数值的有意义排列方法所得的组合
- 表达式最终都会有一个结果,返回给我们,我们称为返回值
// 是由数字、运算符、变量等组成的式子 称为表达式 1+1
console.log(1 + 1); //2就是返回值
// 1+1=2
// 在程序里面2=1+1 把右边表达式计算完毕把返回值给左边
var num = 1 + 1;
console.log(num);//2
2. 递增和递减运算符
2.1 概述
- 如果需要反复给数字变量加或者减去1,可以使用
递增(++)和递减(--)运算符来完成 - 在JS中,
递增(++)和递减(--)既可以放在变量前面也可以放在变量后面 - 放在变量前面时,可以称之为
前置递增/递减运算符 - 放在变量后面时,可以称之为
后置递增/递减运算符
2.2 前置递增/递减运算符
++num前置递增,就是自加1,类似于num = num + 1
var n = 10; n = n + 1; console.log(n) // 11
var m = 10; ++m; console.log(m) // 11
- **注意:**先加1,后返回值
var n = 10; console.log(++n + 10)// 21
2.3 后置递增/递减运算符
num++后置递增,就是自加1,类似于num = num + 1- 前置自增和后置自增如果单独使用,效果是一样的
var n = 10; n++; console.log(n) // 11
var m = 10; console.log(m++ + 1); // 20 console.log(m)// 11
- 注意先返回值,再加1
var a = 10; a++; var b = a++ + 2; console.log(b)// 13
2.4 前置递增和后置递增小结
- 前置递增和后置递增运算符简化代码的编写,写法更简单
- 单独使用时运算结果相同
- 与其他代码连用时,执行结果会不同
- 前置:先自加,后运算(先己后人)
- 后置:先原值运算,后自加(先人后已)
- 开发时,大多使用后置递增/递减,代码独占一行
3. 比较运算符
3.1 概述:比较运算符(关系运算符)是两个数据进行比较时所使用的运算符,比较运算后,会返回一个布尔值
<: 小于号,1 < 2; // rue>: 大于号,1 > 2; // false>=: 大于等于号(大于或等于),2 >= 2; // true<=: 小于等于号(小于或者等于),3 <= 2; // false==: 判等号(会转型),37 == '37'; // true!=: 不等号,37 != '37'; // false===: 全等, 要求值和数据类型都一致,37 === '37';// fslse!==: 全不等, 要求值和数据类型都不一致,37 !== '37';// true
3.2 =小结
=: 赋值,把右边给左边==: 判断,判断两边的值是否相等(注意此时有隐式转换)===: 全等,判断两边的值和数据类型是否完全相等
4. 逻辑运算符
4.1 概述:逻辑运算符是用来进行布尔值运算的运算符,其返回值也是布尔值,开发中常用于多个条件的判断
4.2 &&: 逻辑与,简称与 and,true && false
- 两边都是true才返回true,否则返回false
4.3 ||: 逻辑或,简称或 or, true || false
- 两边都为false才返回false,否则都为true
4.4 !: 逻辑非,简称非 not, !true
- 逻辑非
!,也叫取反符,用来取一个布尔值相反的值,如true的取反值是false
4.5 ?.: 可选链操作符
- 当你访问某个对象的属性或者调用某个属性上的方法时,如果这个对象的值为undefined或者null,那么语句执行就会报错
- 以往我们加一层判断来确保访问的对象不为undefined或者null,然后才做后续操作,繁琐不够优雅
?.作用就是如果对象的属性值为undefined或者null时候,不做后续操作
let obj = {
step1: {
name: '步骤一',
step2: {
name: '步骤二'
}
}
}
// 如果访问step2的name属性,即obj.step1.stpe2.name
// 为了确保安全性,以前我们可能要写如下代码
if(obj && obj.step1 && obj.step.step2 && obj.step1.step2.name) {
obj.step1.step2.name.toString()
}
// 用可选链的话
obj?.step1?.step2?.name?.toString()
4.6 ??: 控制合并操作符
- 这是一个逻辑操作符,与
||操作符十分相似,但是并不是等价的
let a = 0
let b = ''
let c = null
let d = undefined
let x = a ?? 100 // x 等于 0
let y = b ?? 100 // y 等于 ''
let z = c ?? 100 // z 等于 100
let k = d ?? 100 // k 等于 100
let o = a || 100 // o 等于 100
let p = b || 100 // p 等于 100
let q = c || 100 // q 等于 100
let r = d || 100 // r 等于 100
??只有当操作符左侧表达式的值为undefined或者null时,才会返回右侧的值||只要操作符左侧表达式的值为false时,就会返回右侧的值。左侧的表达式会自动做布尔运算,因为0和空字符串做布尔运算为false
4.7 ??=: 空值赋值操作符
- 只有当
??=左侧的值为null或者undefined的时候,才会将右侧变量的值赋值给左侧变量,其他所有值都不会进行赋值
let a = null
let b = undefined
let c = 100
let d = 200
a ??= c // a = 100
// 因为 a 的值为 null,所以会将 c 的值赋值给 a , 所以最终 a = 100
b ??= d // b = 200
// 因为 b 的值为 undefined,所以会将 d 的值赋值给 b , 所以最终 b = 200
4.8 _数值分割符
- ES2021引入数值分隔符
_,在数值组之间提供分割,使一个长数值读起来更容易,Chrome已经提供了对数值分隔符的支持
let number = 100_0000_0000_0000 // 0太多了不用数值分割符眼睛看花了
console.log(number) // 输出 100000000000000
- 十进制的小数部分也可以使用数值分隔符,二进制、十六进制也可以使用数值分隔符
0x11_1 === 0x111 // true 十六进制
0.11_1 === 0.111 // true 十进制的小数
0b11_1 === 0b111 // true 二进制
4.9 ,:逗号运算符
- 逗号操作符对它的每个操作数求值(从左到右),并返回最后一个操作数的值
expr1, expr2, expr3...: 会返回最后一个表达式expr3的结果,其他表达式只会进行求值
4.10 #:私有方法/属性
- 在一个类里面可以给属性前面增加
#私有标记的方式来标记为私有,getter/setter也可以标记为私有,方法也可以标记为私有
class Person {
getDesc() { return this.#name + '' + this.#getAge()}
#getAge() { return this.#age } // 私有方法
get #name() { return 'foo' } // 私有访问器
#age = 22 // 私有属性
}
const a = new Person()
console.log(a.age) // undefined 直接访问不到
console.log(a.getDesc()) // foo 22
5. 赋值运算符
function reverse(arr) {
return [arr[0], arr[1]]=[arr[1], arr[0]], arr[0] + arr[1]
}
const list = [1, 2]
reverse(list) // 返回 3,此时 list 为[2, 1]
5.1 用来把数据赋值给变量的运算符
=: 直接赋值,var a = '我是值'+=、-=: 加、减一个数后再赋值,var a = 10; a += 5 // 15*=、/=、%=: 乘、除、取模后再赋值,var a = 2; a *= 5 // 10
6. 双位运算符~~
- 可以使用双位操作符来替代正数的
Math.floor(), 替代负数的Math.ceil(), - 双位运算符的优势在于它执行相同的操作运算符速度更快
~~4.5 // 4
Math.floor(4.5) // 4
Math.ceil(4.5) // 5
~~-4.5 // -4
Math.floor(-4.5) // -5
Math.ceil(-4.5) // -4
7. 运算符的优先级
一元运算符里面的逻辑非优先级很高,逻辑与比逻辑或优先级高
- 优先级1,小括号,
() - 优先级2,一元运算符,
++ -- ! - 优先级3,算数运算符,
先 * / % 后 + - - 优先级4,关系运算符,
> >= < <= - 优先级5,相等运算符,
== != === !== - 优先级6,逻辑运算符,
先&&后|| - 优先级7,赋值运算符,
= += -= *= /= %= - 优先级8,逗号运算符,
,