都25年了,快用?.替代&&,??替代||

我将创建一个小知识点系列文章,每篇文章只围绕一个很小的知识点展开,阅读成本低,压力小,目的是能够以比较少的时间对一个知识点进行比较扎实的理解和掌握。

最近阅读部门其他人写的代码的时候,发现还有人没有使用链判断运算符?.和Null判断运算符??,而还是使用原始的判断方式。所以我想说都25年了,竟然还不知道这么方便的运算符吗,还不快快用起来!哈哈哈~

一、链判断运算符?.

当我们读取一个对象内部比较深层的属性的时候,往往需要判断一下,属性的上层对象是否存在,以前的写法会是下面这种判断方式:

js 复制代码
// 错误的写法
const  firstName = message.body.user.firstName || 'default';

// 正确的写法
const firstName = (message
  && message.body
  && message.body.user
  && message.body.user.firstName) || 'default';

但是这种写法需要层层判断对象是否存在,很是麻烦。而使用链判断运算符?.,简化后的写法如下:

js 复制代码
const  firstName = message?.body?.user?.firstName || 'default';

?表示判断左侧的对象是否存在,如果存在则继续进行后面点.的读取的操作。如果左侧的对象是null或undefined,则不再往下读取,直接返回undefined。

三种写法

  • obj?.prop // 对象属性是否存在
  • obj?.[expr] // 同上
  • func?.(...args) // 函数或对象方法是否存在

对于对象的属性和方法都可以使用链判断运算符进行读取。注意该运算符是?.构成的整体?.?表示判断左侧的对象是否存在,.表示继续向下读取对象的属性或方法或者进行方法的调用。

如上的后两种写法,通过方括号读取属性和进行方法调用的时候,我们可能习惯性的会只写一个?进行判断,这里需要注意一下哈。

注意

避免过度使用,不要用于已确定存在的对象

链判断运算符的核心作用是 "处理可能不存在的对象 / 属性",如果对象或属性是明确存在的(如自己定义的普通对象、框架提供的必选参数),则不需要进行链判断,过度使用?.会增加代码冗余。 如下是一个错误示例:

js 复制代码
// 自己定义的obj,明确存在name属性,无需使用?.
const obj = { name: '张三' };
const name = obj?.name; // 多余的?.,应直接写obj.name

不能用于左侧赋值

?.仅支持 "读取属性 / 调用方法",不允许用于赋值语句的左侧。这是因为链判断的核心是 "安全读取",而赋值需要明确的目标对象,若左侧对象不存在,赋值行为本身就是无效的。如下是一个错误示例:

js 复制代码
// 语法错误:Uncaught SyntaxError: Invalid left-hand side in assignment
message?.body?.user?.firstName = '张三';

二、Null判断运算符

读取对象属性时,如果某个属性的值是null或undefined,也就是不存在或者未指定初始值的情况,有时需要为它们指定默认值。

以前的做法是通过||短路运算符指定默认值,当左侧的计算值为false的时候,则会读取||右侧的值。但是属性的值如果为空字符串或false或0,都会被转为false值,此时默认值都会生效。但这不是我们所期望的,有的时候我们就是想将值设置为空字符串或false或为0啊。这个时候就可以使用Null判断运算符进行处理。

Null判断运算符??的行为类似短路运算符||,但是只有运算符左侧的值为null或undefined时,才会返回右侧的值,这正是我们期望的设置默认值的情况。

js 复制代码
const headerText = response.settings.headerText ?? 'Hello, world!';
const animationDuration = response.settings.animationDuration ?? 300;
const showSplashScreen = response.settings.showSplashScreen ?? true;

如上.headerText可能为空字符串"",.animationDuration可能为0.showSplashScreen可能为false,使用??配置默认值的时候,均不会影响这些值的生效。

三、两个运算符的结合使用

将链判断运算符?.和Null判断运算符??结合使用是比较常用的方式。前者进行属性的判断和读取,当读取不到值的时候,则通过后者进行默认值的设置。

js 复制代码
const headerText = response.settings?.headerText ?? 'Hello, world!';
const animationDuration = response.settings?.animationDuration ?? 300;
const showSplashScreen = response.settings?.showSplashScreen ?? true;

如上response.settings对象上可能不存在.headerText.animationDuration.showSplashScreen三个配置项属性,因此先通过?.进行判断,并且分别为三个配置项通过??设置了默认值,这样的读取方式才更为安全。

最后

希望对大家有所帮助,并给予点赞哈~

相关推荐
Asort5 小时前
JavaScript设计模式(十八)——备忘录模式:状态保存与恢复的艺术
前端·javascript·设计模式
社恐的下水道蟑螂5 小时前
一文吃透 JS 对象字面量:从基础用法到代理模式实践
javascript
一枚前端小能手5 小时前
🔄 重学Vue之nextTick和slot - 从底层实现到实战应用的完整指南
前端·javascript·vue.js
有意义5 小时前
从HTML敲击乐了解开发流程
javascript
烟袅5 小时前
JavaScript 中的 null 与 undefined:你真的搞懂它们的区别了吗?
javascript
有点笨的蛋5 小时前
“花”点心思学代理:JavaScript中的对象与中介艺术
javascript
Hilaku5 小时前
一个函数超过20行? 聊聊我的函数式代码洁癖
前端·javascript·架构
不会算法的小灰5 小时前
JavaScript 核心知识学习笔记:给Java开发者的实战指南
javascript·笔记·学习
crary,记忆6 小时前
Angular如何让整个项目的所有页面能够整体缩小一定的比例?
javascript·ecmascript·angular.js