ES6链判断运算符(?.)的正确打开方式

在实际应用中,如果读取对象内部 的某个属性,往往需要判断一下,属性的上层对象是否存在。比如,读取message.body.user.firstName这个属性,安全的写法是写成下下面这样:

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

上面的例子,firstName属性在对象的第四层,所以需要判断四次,每一层是否有值。三元运算符也常用于判断对象是否存在

const fooInput = myForm.querySelector('input[name=foo]')
const footVal = fooInput ?footInput.value : undefined

上面的例子,必须先判断fooInput是否存在,才能读取fooInput.value

这样层层判断非常麻烦,因此ES2020引入了“链式判断运算符”---?.,简化上面的写法 

const firstName = message?.body?.user?.firstName || 'default'
const fooVal = myForm.querySelector('input[name=foo]')?.value

上面代码中使用了?.运算符,直接在链式调用的时候判断,左侧的对象是否为null或者undefined,如果是的,就不再往下运算,而是返回undefined

下面是判断 对象方法是否存在,如果存在就立即执行的例子

iterator.return?.()

上面的代码中,iterator.return如果有定义,就会调用该方法,否则iterator.return直接返回undefined,不再执行?.后面的部分

对于那些可能没有实现的方法,这个运算符尤其有用

if(myForm.checkValidity?.()===false){return
}

上面代码中,老式浏览器的表单对象可能没有checkValidity()这个方法,这时?.运算符就会返回undefined,判断语句就变成了undefined===false,所以就会跳过下面的代码

链式判断运算符?.有是那种写法

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

下面是obj?.[expr]用法的一个例子

let hex = "#C0FFEE".match(/#([A-Z]+)/i)?.[1];

上面代码中,字符串match()方法,如果没有发现匹配会返回null,如果发现匹配会返回一个数组,?.运算符起到了判断作用

下面?.运算符常见形式,以及不实用运算符时的等价形式

a?.b
// 等同于
a ===  null ? undefined : a.ba?.[x]
a === null ? undefined :a[x]a?.b()
a === null ? undefined :a.b()a?.()
a === null ? undefined : a()

上面的代码 中,特别注意后面两种形式, a?.b()a?.(),如果a?.b()里面的a.b有值,但不是函数,不可调用。那么a?.b()是会报错的。a?.()也是如此,如果a不是nullundefined,但也不是函数,那么a?.()会报错

使用这个运算符,有几个注意点:

1)短路机制

本质上,?.运算符相当于一个短路机制,只要不满足条件,就不会往下执行

a?.[++x]
// 
a === null ? undefined : a[++x]

上面代码中,如果a是undefined或者null,那么x不会进行递增运算。也就是说,链式判断运算符一旦不为真,右侧的表达式就不再求值。

2)括号的影响

如果属性链有圆括号,链判断运算符对圆括号外部没有影响 ,只对圆括号内部有影响

(a?.b).c
//
(a === null ? undefined : a.b).c

上面代码中,?.对圆括号外部没有影响,不管a对象是否存在,圆括号后面的.c总是会执行。

一般来说,使用?.运算符的场合,不应该使用圆括号。

3)报错场合

以下写法是错误的,会报错

// 构造函数
new a?.()
new a?.b()// 链判断运算符的右侧有模板字符串
a?.`{b}`
a?.b`{c}`// 链判断运算符的左侧是 super
super?.()
super?.foo// 链运算符用于赋值运算符左侧
a?.b = c

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/29447.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

探索 TypeScript 元组的用例

元组扩展了数组数据类型的功能。使用元组,我们可以轻松构造特殊类型的数组,其中元素相对于索引或位置是固定类型的。由于 TypeScript 的性质,这些元素类型在初始化时是已知的。使用元组,我们可以定义可以存储在数组中每个位置的数…

Android, 笔记+课表的app实现

NoteSchedule: 笔记课表,不同于超表和课程格子等笔记类软件,笔记课表的核心是将课表和笔记进行深度绑定,点击每个课表,就进入到笔记view中,点击其中的item就可以进入到笔记详情; 该应用已上线,…

回归预测 | MATLAB实现POA-CNN-LSTM鹈鹕算法优化卷积长短期记忆神经网络多输入单输出回归预测

回归预测 | MATLAB实现POA-CNN-LSTM鹈鹕算法优化卷积长短期记忆神经网络多输入单输出回归预测 目录 回归预测 | MATLAB实现POA-CNN-LSTM鹈鹕算法优化卷积长短期记忆神经网络多输入单输出回归预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 MATLAB实现POA-CNN…

Creo散热处理结构设计--阵列操作

问题描述: 在某一平面掏孔以散热,如何快速的绘制多孔并掏空处理 解决方式: 采用阵列操作。 1)绘制圆、拉伸处理 2)选择需要阵列的单元,选择阵列操作,在弹出的界面选择方向,按照…

【Winform学习笔记(七)】Winform无边框窗体拖动功能

Winform无边框窗体拖动功能 前言正文1、设置无边框模式2、无边框窗体拖动方法1、通过Panel控件实现窗体移动2、通过窗体事件实现窗体移动3、调用系统API实现窗体移动4、重写WndProc()实现窗体移动 前言 在本文中主要介绍 如何将窗体设置成无边框模式、以及实现无边框窗体拖动功…

C++项目:在线五子棋对战网页版--匹配对战模块开发

玩家匹配是根据自己的天梯分数进行匹配的,而服务器中将玩家天梯分数分为三个档次: 1. 普通:天梯分数小于2000分 2. 高手:天梯分数介于2000~3000分之间 3. 大神:天梯分数大于3000分 当玩家进行对战匹配时,服…

[分享]STM32G070 串口 乱码 解决方法

硬件 NUCLEO-G070RB 工具 cubemx 解决方法 7bit 改为 8bit printf 配置方法 添加头文件 #include <stdio.h> 添加重定向代码 #ifdef __GNUC__#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)#else#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)#endi…

并发多线程篇

线程的基础知识 面试题1&#xff1a;线程与进程的区别&#xff1f; 面试题2&#xff1a;并行和并发有什么区别&#xff1f; 面试题3&#xff1a;创建线程的方式有哪些&#xff1f; 面试题 4&#xff1a;runnable 和 callable 有什么区别&#xff1f; 面试题5&#xff1a;线程…

Postgresql源码(110)分析dsm动态共享内存分配与共享内存mq实例(dsm/toc接口备忘录)

相关 《Postgresql源码&#xff08;90&#xff09;共享内存申请CreateSharedMemoryAndSemaphores》 《Linux内存映射函数mmap与匿名内存块》 《Linux共享内存与子进程继承》 dsm/toc使用备忘 用dsm框架的流程 评估共享内存大小&#xff1a;多次用shm_toc_estimate_chunk、shm…

Git 快速入门

Git 快速入门 文章目录 Git 快速入门一、代码托管平台&#xff08;远程仓库&#xff09;二、安装Git三、Git的命令实践Git 的四个区域Git 管理代码的3个场景Git 工作区的理念Git 工作区的生命周期Git 版本回退Git 文件重命名Git查看版本提交日志Git StashGit分支Git标签 四、创…

Nginx与docker配置安装

目录&#xff1a; Nginx的安装配置&#xff1a; 1、安装依赖包&#xff1a; 2、下载Nginx安装包&#xff1a; 3、解压Nginx压缩包&#xff1a; 4、配置Nginx编译环境&#xff1a; 5、编译并安装Nginx&#xff1a; 6、安装完Nginx后&#xff0c;可以切换到Nginx的安装目录…

【TypeScript】TS接口interface类型(三)

【TypeScript】TS接口interface类型&#xff08;三&#xff09; 【TypeScript】TS接口interface类型&#xff08;三&#xff09;一、接口类型二、实践使用2.1 常规类型2.2 设置属性只读 readonly2.3 设置索引签名2.4 设置可选属性2.5 函数类型接口 一、接口类型 TypeScript中的…

【肌电图信号分析】通道肌电图并查找收缩周期的数量、振幅、最大值和持续时间(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

arcgis宗地或者地块四至权利人信息提取教程

ARCGIS怎样将图斑四邻的名称及方位加入其属性表 以前曾发表过一篇《 如何把相邻图斑的属性添加在某个字段中》的个人心得,有些会员提出了进一步的要求,不但要相邻图斑的名称,还要求有方位,下面讲一下自己的做法。 基本思路是:连接相邻图斑质心,根据连线的角度确定相邻图斑…

dpkg: error: dpkg frontend lock is locked by another process

问题 在Ubuntu 系统终端用&#xff1a; dpkg -i xxxxxxxxxx.deb 安装软件包的时候&#xff0c;报错 dpkg: error: dpkg frontend lock is locked by another process 方案 找到这个锁文件的进程id lsof /var/lib/dpkg/lock-frontend 再kill 掉 sudo kill -9 PID 删除锁文件 …

SQL-每日一题【1164. 指定日期的产品价格】

题目 产品数据表: Products 写一段 SQL来查找在 2019-08-16 时全部产品的价格&#xff0c;假设所有产品在修改前的价格都是 10 。 以 任意顺序 返回结果表。 查询结果格式如下例所示。 示例 1: 解题思路 1.题目要求我们查找在 2019-08-16 时全部产品的价格&#xff0c;假设所…

处理nacos、tomcat、nginx日志增长过快问题

1.nacos日志清理 修改nacos-logback.xml 将日志级别改为error级&#xff0c;减少info级日志产生量 将<maxHistory>调整为2以下&#xff0c;将 <totalSizeCap>调整为2GB左右 比如&#xff1a; [rootiZ0jlapur4hqjezy8waee0Z logs]# ll -h total 2.1G -rw-r--r-…

[Securinets CTF Quals 2023] PolyLCG DigestiveV2

PolyLCG 第1个题是个LCG问题,通过一堆参数生成两个序列&#xff0c;如果flag位为1则输出x序列为0则输出 y序列 from random import randintxcoeff[2220881165502059873403292638352563283672047788097000474246472547036149880673794935190953317495413822516051735501183996…

设计实现数据库表扩展的7种方式

设计实现数据库表扩展的7种方式 在软件开发过程中&#xff0c;数据库是一项关键技术&#xff0c;用于存储、管理和检索数据。数据库表设计是构建健壮数据库系统的核心环节之一。然而&#xff0c;随着业务需求的不断演变和扩展&#xff0c;数据库表中的字段扩展变得至关重要。 …

[OnWork.Tools]系列 06-屏幕水印

简介 屏幕水印功能主要是在开会分享屏幕的时候在屏幕上增加水印 水印使用 水印启用和颜色设置 水印文字和大小设置 水印间距,透明度,角度调整