关于前端:运算符指数链判断Null判断逻辑赋值

77次阅读

共计 3034 个字符,预计需要花费 8 分钟才能阅读完成。

指数运算符

// 2 * 2
console.log(2 ** 2); // 4

// 2 * 2 * 2 * 2
console.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 = 2
a **= 4
console.log(a) // 16

这里相当于是 a = 2 ** 4


链判断运算符

在一段业务逻辑中,常常须要获取对象内的某个属性,该属性在某些场景下可能是不存在的,所以须要判断一下。
在读取对象的深层属性时,平安的写法须要层层判断,防止报错。

let data = {
       user:{
         goods : {num : 100}
       }
}

谬误写法:不平安,因为间接读取对象深层的值,后面的值(user、goods)一但不存在就会报错。

// 谬误写法:不平安
let num = data.user.goods.num || 0

正确写法:层层判断,如果其中有一环不存在就立马返回

// 正确的写法,层层判断,data 存在,并且 data.user 存在.... 其中有一项不存在则返回 0
let num2 = data && data.user && data.user.goods && data.user.goods.num || 0
console.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 || 0
console.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');  // world
console.log(data3?.name || 'default'); // 东方不败
console.log(data3.sayHi?.());  // hello
console.log(data3.sayHi2?.()); // undefined
console.log(data3?.sayHi?.()); // hello

链判断运算符其实有一个短路机制,如果条件不满足则终止执行。

以下场合应用链判断运算符会报错:
1、构造函数
2、链判断运算符右侧有模板字符串
3、链判断运算符左侧是 super
4、链运算符用于赋值运算符左侧

// 构造函数 报错
new a?.()

// 右侧有模板字符串
a?.`${w}`
    
// 左侧是 super
super?.()

// 右侧有赋值
a?.b = 100

留神:链运算符右侧如果是 数字 会生效 ,会被解析成 三元运算符 . 会被解析成数字小数点

let num5 = {1 : 100}
console.log(.123);  // 0.123
console.log(num5?.1 : undefined);  // 这里实际上被解析为 num5 ? .1 : undefined, 变成了三元运算符


Null 判断运算符

在读取对象属性的时候,判断某个属性是否存在,如果属性的值是 nullundefined时, 给该属性一个默认值,常见的做法是用 || 运算符判断是否存在,不存在则返回右侧的值。

|| 运算符存在隐式转换,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 判断运算符,语法:??
它的行为跟 || 运算符基本相同,惟一的不同是它没有隐式转换,只有左侧的值为 nullundefined时才会返回右侧的值。

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); // 0
console.log(back3); // false
console.log(back4); // 不存在

多个逻辑运算符一起应用,必须用 括号 表明 优先级,否则报错

// 报错
a && 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;
a || (b ?? c);

(a ?? b) || c;
a ?? (b || c);


逻辑赋值运算符

es2021引入三个逻辑赋值运算符,将逻辑运算符和赋值运算符联合

let x = 0
let y = 5
let z = x ||= y
let z2 = x ??= y
let z3 = x &&= y

console.log(z); // 5
console.log(z2); // 5
console.log(z3); // 5
console.log(x); // 5

其实这个逻辑赋值运算符和逻辑运算符是一样的,只不过看起来更直观
逻辑运算符:左侧的值不存在就把右侧的值赋值给该对象
逻辑赋值运算符:左侧的值不存在就把右侧的值等于左侧,将左侧的值赋值给该对象

留神:逻辑赋值运算符会更改被赋值的原始值,上述案例中,右侧的 y 赋值给了左侧的 x,左侧的 x =5,所以上面的?? 运算符判断 x =5,导致并没有走右侧的 y 逻辑赋值运算。

let b = 0
let m = 5
let f = b ??= m
console.log(f);  // 0


案例源码:https://gitee.com/wang_fan_w/es6-science-institute

如果感觉这篇文章对你有帮忙,欢送点亮一下 star 哟

正文完
 0