带你了解ECMAScript新的操作符:可选链操作符(?.)、空值合并操作符(??)与逻辑空赋值(??=)

·  阅读 132
带你了解ECMAScript新的操作符:可选链操作符(?.)、空值合并操作符(??)与逻辑空赋值(??=)

可选链操作符(Optional chaining operator):?.

你在学习或工作中肯定写过类似这样的代码:

    if(user.score.english>=90){
        console.log('及格')
    }
复制代码

看似好像没什么问题,确实,如果user对象像下面这样,确实不会有问题:

    const user = {
        username:'谢说前端',
        score:{
            chinese:120,
            math:140,
            english:110
        }
    }
复制代码

但你有没有想过,如果user.score属性不存在,或者这个数据是ajax请求回来的,在数据没回来之前就进行判断,就会抛出如下错误

image.png

以前你可能会这么解决:

     if(user.score && user.score.english>=90){
        console.log('及格')
    }
复制代码

使用可选链操作符改造一下:

    if(user.score?.english){
        console.log('及格')
    }
复制代码

是不是很爽?

爽.webp

官方解释:
可选链操作符 是ES2020(ES10)推出的新特性,允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。?. 与 . 链式操作符不同之处在于,在引用为空(null或 undefined) 的情况下不会引起错误,该表达式短路返回值是 undefined

可选链操作符语法

可用在对象、数组、函数调用等语法中

  • obj?.prop
  • obj?.[expr]
  • arr?.[index]
  • func?.(args)
    user?.score
    user?.['score']
    user.hobby?.[2]
    user.show?.()
复制代码

浏览兼容性

image.png

实际中的案例

以下为某同学在写Vue项目时经常犯的错(为了更容易理解,我简化了代码)

    <template>
        <div>
            <p>用户名:{{user.username}}</p>
            <p>英语成绩:{{user.score.english}}</p>
        </div>
    </template>
    <script>
        export default {
            data(){
                return {
                    user:{}
                }
            },
            created(){
                this.getUserInfo().then((data)=>{
                    this.user = data.data
                })
            }
            //... 省略部分代码
        }
    </script>
复制代码

最终的效果是效果能出来,但控制台会报一个错误,很初学者一直搞不懂,明明效果出来了,为什么还扬子报错?

其实是因为刚开始渲染视图时由于user是一个空对象,对象中并没有score属性,user.score得到undefined,自然就不能继续user.score.english了,所以才报错,后面数据回来后成功渲染到页面

解决报错问题,以前你可以会这么做:

    <p>英语成绩:{{user.score && user.score.english}}</p>
复制代码

是不是很麻烦?什么?不麻烦?那你来写(如果你还是觉得不麻烦就当我没说......)

    <p>英语成绩:{{user.score && user.score.english}}</p>
    <p>数学成绩:{{user.score && user.score.math}}</p>
    <p>语文成绩:{{user.score && user.score.chinese}}</p>
复制代码

有了可选链操作符,你可以这么写:

    <p>英语成绩:{{user.score?.english}}</p>
复制代码

当数据没有请求回来时该表达式短路得到undefined,Vue会忽略掉nullundefined的值,故一开始不显示也不报错,直到数据返回后显示

空值合并操作符(Nullish coalescing operator):??

以前我们用得比较多的应用是逻辑与&&和逻辑或||,用于短路赋值操作。

我想从本地存储中拿到用户信息,但本地存储中user可能不存在,也有可能是空字符串,我的需求如下:

  1. 当本地存储不存在user时赋值一个空对象
  2. user有值时(哪怕是空字符串)也要保持这个值

一般我们写代码会这样写:

    let user = localStorage.getItem('user') || {}
    try{
        user = JSON.parse(user)
    }catch{
        
    }
复制代码

但上面代码其实会有一个问题,如果localStoreage.getItem('user')得到的是一个空字符串,还是会赋值空对象,用??就不会有问题,因为它只判断nullundefined的情况,而当本地存储中不存在user时得到的刚好是null,so

    let user = localStorage.getItem('user') ?? {}
    try{
        user = JSON.parse(user)
    }catch{
        
    }
复制代码

ok,完美实现上面需求

官方解释:
空值合并操作符?? )是一个逻辑操作符,当左侧的操作数为 nullundefined时,返回其右侧操作数,否则返回左侧操作数

浏览器兼容性

image.png

操作符对比

  • left || right : 如果leftTruthy,则返回left否则返回right
  • left && right : 如果leftTruthy,则返回right否则返回left
  • left ?? right : 如果leftnullundefined,则返回right否则返回left
  • Truthy:真值,即转成Boolean类型为true的值
  • Falsy:假值,即转成Boolean类型为false的值

来一波代码理解以上操作符:

    const result = 0 || 'ok'; // 'ok'
    const result = 1 || 'ok'; // 1
    const result = null || 'ok'; // 'ok'
    const result = true || 'ok'; // true
    
    const result = 0 && 'ok'; // 0
    const result = 1 && 'ok'; // 'ok'
    const result = null && 'ok'; // null
    const result = true && 'ok'; // 'ok'
    
    const result = 0 ?? 'ok';// 0
    const result = 1 ?? 'ok';// 1
    const result = null ?? 'ok';// 'ok'
    const result = true ?? 'ok'; // true
复制代码

如果只是做赋值操作,其实还有一个更合适的操作符: 逻辑空赋值:??=,接着往下看

逻辑空赋值(Logical nullish assignment):??=

逻辑空赋值??=顾名思义就是用来赋值的,传统的=是直接赋值,而??=根据条件赋值(当左边的变量值为Nullish时才赋值),条件判断与??一至(当左边为null或undefined时才符合条件)

Nullish: 空值,即null或undefined

仍然是通过一波代码了解它的用法:

    let pos = {x:10}
    pos.x ??= 20; // pos.x不为null或undefined,故不赋值,所以pos.x仍然保持10
    pos.y ??= 50; // pos.y为undefined,所以赋值50为pos.y
复制代码

浏览器兼容性

image.png

很多小伙伴可能要说,什么,IE又不支持?
都什么年代了还抓着IE不放,大清已经灭亡,我们要住前看!
虽说有些可能还没成为正式的标准,但主流的浏览器已经完美支持,
退一万步来说,我们不是还有强大的babel么?怕啥

结语

好了,以上就是本篇文章所有内容,主要让大家了解三个新的操作符,学会后可以在很多时候简化我们的代码操作,大家也看到,随着ECMAScript版本不断升级,会有越来越多的好玩的新特性,请继续关注我,带你了解更多的前端知识

分类:
前端
标签:
收藏成功!
已添加到「」, 点击更改