指数运算符
// 2 * 2console.log(2 ** 2); // 4// 2 * 2 * 2 * 2console.log(2 ** 4); // 16
指数运算符是右联合,多个指数运算符连用时,从左边开始计算。
console.log(2 ** 3 ** 2); // 512// 2 ** (3 ** 2)// 2 ** 9// 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2
指数运算符能够与等号联合,变成赋值运算符 **=
let a = 2a **= 4console.log(a) // 16
这里相当于是 a = 2 ** 4
链判断运算符
在一段业务逻辑中,常常须要获取对象内的某个属性,该属性在某些场景下可能是不存在的,所以须要判断一下。
在读取对象的深层属性时,平安的写法须要层层判断,防止报错。
let data = { user:{ goods : { num : 100 } }}
谬误写法:不平安,因为间接读取对象深层的值,后面的值(user、goods
)一但不存在就会报错。
// 谬误写法:不平安let num = data.user.goods.num || 0
正确写法:层层判断,如果其中有一环不存在就立马返回
// 正确的写法,层层判断,data存在,并且data.user存在....其中有一项不存在则返回0let num2 = data && data.user && data.user.goods && data.user.goods.num || 0console.log(num2); // 100
三元表达式:正确写法,层层判断,直到找到最初一层
let num3 = data ? data.user ? data.user.goods ? data.user.goods.num ? data.user.goods.num : 0 : '暂无商品' : '用户不存在' : []console.log(num3); // 100
然而这种写法十分麻烦,须要层层判断,因而es2020
引入了"链判断运算符
"。
链判断运算符:语法:?.
链判断运算符用来简化下面的写法,如果其中有一项不满足则返回右侧的值
let num4 = data?.user?.goods?.num || 0console.log(num4); // 100
链判断运算符能够判断对象内的函数是否存在,如果存在就立刻执行,不存在则返回undefined
let data2 = { chains(){ return '存在'} }console.log(data2.chains?.()); // 存在console.log(data2.chains2?.()); // undefined
留神:一般函数是无奈通过链判断运算符判断是否存在的,如果不存在会间接报错
function chains(){ return '存在'}console.log(chains?.()); // 存在// console.log(chains2?.()); // 不存在 报错
链判断运算符的几个应用办法
let w = 'hello'let data3 = { [w] : 'world', // 表达式键名 name : "东方不败", // 一般属性 sayHi(){ return 'hello' } // 对象内函数}console.log(data3?.[w] || 'default'); // worldconsole.log(data3?.name || 'default'); // 东方不败console.log(data3.sayHi?.()); // helloconsole.log(data3.sayHi2?.()); // undefinedconsole.log(data3?.sayHi?.()); // hello
链判断运算符其实有一个短路机制,如果条件不满足则终止执行。
以下场合应用链判断运算符会报错:
1、构造函数
2、链判断运算符右侧有模板字符串
3、链判断运算符左侧是 super
4、链运算符用于赋值运算符左侧
// 构造函数 报错new a?.()// 右侧有模板字符串a?.`${w}` // 左侧是supersuper?.()// 右侧有赋值a?.b = 100
留神:链运算符右侧如果是数字
将会生效
,会被解析成三元运算符
,.
会被解析成数字小数点
let num5 = { 1 : 100}console.log(.123); // 0.123console.log(num5?.1 : undefined); // 这里实际上被解析为num5 ? .1 : undefined,变成了三元运算符
Null判断运算符
在读取对象属性的时候,判断某个属性是否存在,如果属性的值是null
或undefined
时,给该属性一个默认值,常见的做法是用||
运算符判断是否存在,不存在则返回右侧的值。
||
运算符存在隐式转换,0、null、undefined
、空字符串都会被转换为false
let n = { user : '东方不败', status : 0}let u = n.user || '用户不存在'let u2 = n.user2 || '用户不存在'console.log(u); // 东方不败console.log(u2); // 用户不存在 let u3 = n.status || '不存在'console.log(u3); // 不存在
||
运算符更适宜判断属性是否为假(false
),而不是null、undefined
es2020
提供了新的null
判断运算符,语法:??
它的行为跟 ||
运算符基本相同,惟一的不同是它没有隐式转换,只有左侧的值为null
或undefined
时才会返回右侧的值。
let judge = { user : "东方不败", num : 0, status : false, em : null}let back = judge.user ?? '不存在'let back2 = judge.num ?? '不存在'let back3 = judge.status ?? '不存在'let back4 = judge.em ?? '不存在'console.log(back); // 东方不败console.log(back2); // 0console.log(back3); // falseconsole.log(back4); // 不存在
多个逻辑运算符一起应用,必须用括号
表明优先级
,否则报错
// 报错a && b ?? ca ?? b && ca || b ?? ca ?? b || c
// 正确的写法, 加上括号表明优先级(a && b) ?? c;a && (b ?? c);(a ?? b) && c;a ?? (b && c);(a || b) ?? c;a || (b ?? c);(a ?? b) || c;a ?? (b || c);
逻辑赋值运算符
es2021
引入三个逻辑赋值运算符,将逻辑运算符和赋值运算符联合
let x = 0let y = 5let z = x ||= ylet z2 = x ??= ylet z3 = x &&= yconsole.log(z); // 5console.log(z2); // 5console.log(z3); // 5console.log(x); // 5
其实这个逻辑赋值运算符和逻辑运算符是一样的,只不过看起来更直观
逻辑运算符:左侧的值不存在就把右侧的值赋值给该对象
逻辑赋值运算符:左侧的值不存在就把右侧的值等于左侧,将左侧的值赋值给该对象
留神:逻辑赋值运算符会更改被赋值的原始值,上述案例中,右侧的y赋值给了左侧的x,左侧的x=5,所以上面的??运算符判断x=5,导致并没有走右侧的y逻辑赋值运算。
let b = 0let m = 5let f = b ??= mconsole.log(f); // 0
案例源码:https://gitee.com/wang_fan_w/es6-science-institute
如果感觉这篇文章对你有帮忙,欢送点亮一下star哟