运算符扩展
可选链操作符 (?.)
我们来看一个项目中常见的场景:
let xuan = {
xuan2: {
}
};
console.log(xuan.xuan2.xuan3); // undefined
console.log(xuan.xuan2.xuan3.xuan4);
// Uncaught TypeError: Cannot read properties of undefined (reading 'xuan4')
可能你会问为什么第一条输出不会报错,但第二条输出会报错。我的理解是 从已定义的对象身上取未定义的值是可以的,但是从undefined身上取值会报错,因为xuan3未定义值为undefined所以才会报错。
可以看出来以上取值方式是危险的,搞不好中间哪一步就为undefined。那么有什么办法可以安全的取值呢?有,那就是&&短路运算符
let i = 1
console.log(i++ && false && i++); // false
console.log(i); // 2
console.log(true && 2 && 0 && 4); // 0
所谓&&逻辑运算符就是当有一个条件不满足,那么就不会继续判断后面的条件,并且输出最后一个导致终止的值
总所周知,在JavaScript中null和undefined的布尔值是为false,那么我们是否可以利用这个小特性实现安全取值
let xuan = {
xuan2: {
},
};
console.log(xuan && xuan.xuan2 && xuan.xuan2.xuan3 && xuan.xuan2.xuan3.xuan4);
// undefined
可以看到,当进行到了xuan.xuan2.xuan3这一步时值为undefined,就会终止后续判断。
我的天啊,安全是安全了,可是多了这么多代码,那有没有什么办法既能安全又能简洁呢,当然有,此时我们的主角?.可选链操作符出场了
let xuan = {
xuan2: {
},
};
console.log(xuan?.xuan2?.xuan3?.xuan4); // undefined
?. 操作符的功能类似于 . 链式操作符,不同之处在于,在引用为空(nullish ) (null 或者 undefined) 的情况下不会引起错误,该表达式短路返回值
空值合并操作符 (??)
我们来看这么一个场景:
let xuan = {
xuan2: {
},
};
let flag = xuan.xuan2.xuan3
console.log('我的名字叫' + flag); // 我的名字叫undefined
没有从业计算机行业的朋友看到这一幕会觉得好有个性,名字居然叫未定义。但是我们看到这一幕就会知道是取值出问题了。此时我们希望如果用户没设置名字,那么就给他设置一个兜底值要怎么做?
||短路运算符
console.log(false || false || '轩小浅'); // 轩小浅
console.log(false || '轩小浅' || '喜洋洋'); // 轩小浅
console.log(false || false || 0); // 0
所谓||逻辑运算符就是当有一个表达式布尔值为true,那么就不会继续后面的判断,并且输出第一个导致终止的值,如果布尔值都不为true那么就输出最后一个值。
因为undefined在布尔值里面为false,那我们可以用||实现设置兜底值
let xuan = {
xuan2: {
},
};
let flag = xuan.xuan2.xuan3 || '轩小浅' // 如果第一个表达式不为true,那么将后面的值赋值给flag
console.log('我的名字叫' + flag); // 我的名字叫轩小浅
可以看到成功了,但,真的没有一点问题吗?我们来看下面一段代码
let xuan = {
xuan2: {
xuan3:0,
xuan4:'',
},
};
let flag = xuan.xuan2.xuan3 || '轩小浅'
let flag2 = xuan.xuan2.xuan4 || '喜洋洋'
console.log('我的名字叫' + flag); // 我的名字叫轩小浅
console.log('我的名字叫' + flag2); // 我的名字叫喜洋洋
可以看到,明明用户设置了名字,为什么还是动用了兜底值?因为在JavaScript中空字符串和0的布尔值都为false
聪明的你一拍脑门就写出了下面的代码:
let xuan = {
xuan2: {
xuan3: 0,
xuan4: '',
},
};
let flag = xuan.xuan2.xuan3;
let flag2 = xuan.xuan2.xuan4;
if (flag === (undefined || null)) {
flag = '轩小浅'
}
if (flag2 === (undefined || null)) {
flag2 = '喜洋洋'
}
console.log('我的名字叫' + flag); // 我的名字叫0
console.log('我的名字叫' + flag2); // 我的名字叫
是的,判断一下不就行了吗?但是你看了一眼身边的大佬是这样写的:
let xuan = {
xuan2: {
xuan3: 0,
xuan4: '',
},
};
let flag = xuan.xuan2.xuan3 ?? '轩小浅';
let flag2 = xuan.xuan2.xuan4 ?? '喜洋洋';
let flag3 = xuan.xuan2.xuan5 ?? '灰太狼';
console.log('我的名字叫' + flag); // 我的名字叫0
console.log('我的名字叫' + flag2); // 我的名字叫
console.log('我的名字叫' + flag3); // 我的名字叫灰太狼
看完后你含着泪花默默改掉自己刚刚写的代码。
??是一个逻辑操作符,当左侧的操作数为 null 或者 undefined 时,返回其右侧操作数,否则返回左侧操作数。
两者配合使用
let xuan = {
xuan2: {
},
};
let flag = xuan?.xuan2?.xuan3?.xuan4 ?? '轩小浅';
console.log(flag);
\