最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • ES2021让代码更优美的运算符 (?.) (??)

    正文概述 掘金(李白不吃茶v)   2021-01-03   571

    链判断运算符(?.)

    非常好用、常用,搭配Null 判断运算符使用,效果更佳,完美!

    来,上代码:

    我们通常获取一个对象多层的属性值时,需要进行多次的判断。如不判断,一个为空则报错,导致后面无法继续下去。

    // error
    const  firstName = message.body.user.firstName;

    // ok
    const firstName = (message
      && message.body
      && message.body.user
      && message.body.user.firstName) || 'default';

    也可以用三元运算符?:来判断单个值,下面例子中,必须先判断fooInput是否存在,才能读取fooInput.value

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

    接着,我们来使用 ?. 运算符看看有多神奇:

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

    一气呵成,直接在链式调用的时候判断,左侧的对象是否为nullundefined。如果是,就不再往下运算,直接返回undefined

    链判断运算符有三种用法。

    • obj?.prop // 对象属性
    • obj?.[expr] // 同上
    • func?.(...args) // 函数或对象方法的调用
    "#C0FFEE".match(/#([A-Z]+)/i)?.[1]  // 无匹配返回null,匹配则返回一个数组

    a?.b
    // 等同于
    a == null ? undefined : a.b

    a?.[x]
    // 等同于
    a == null ? undefined : a[x]

    a?.b()
    // 等同于
    a == null ? undefined : a.b()

    a?.()
    // 等同于
    a == null ? undefined : a()

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

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

    (1)短路机制

    ?.运算符相当于一种短路机制,只要不满足条件,就不再往下执行。

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

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

    (2)delete 运算符

    delete a?.b
    // 等同于
    a == null ? undefined : delete a.b

    上面代码中,如果aundefinednull,会直接返回undefined,而不会进行delete运算。

    (3)括号的影响

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

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

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

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

    (4)报错场合

    以下写法是禁止的,会报错。

    // 构造函数
    new a?.()
    new a?.b()

    // 链判断运算符的右侧有模板字符串
    a?.`{b}`
    a?.b`{c}`

    // 链判断运算符的左侧是 super
    super?.()
    super?.foo

    // 链运算符用于赋值运算符左侧
    a?.b = c

    (5)右侧不得为十进制数值

    为了保证兼容以前的代码,允许foo?.3:0被解析成foo ? .3 : 0,因此规定如果?.后面紧跟一个十进制数字,那么?.不再被看成是一个完整的运算符,而会按照三元运算符进行处理,也就是说,那个小数点会归属于后面的十进制数字,形成一个小数。

    Null 判断运算符(??)

    读取对象属性的时候,如果某个属性的值是nullundefined,有时候需要为它们指定默认值。常见做法是通过||运算符指定默认值。

    const headerText = response.settings.headerText || 'Hello, world!';
    const animationDuration = response.settings.animationDuration || 300;
    const showSplashScreen = response.settings.showSplashScreen || true;

    上面的三行代码都通过||运算符指定默认值,属性的值如果为''false0,默认值也会生效。

    为了避免这种情况,ES2020 引入了一个新的 Null 判断运算符??。它的行为类似||,但是只有运算符左侧的值为nullundefined时,才会返回右侧的值。

    const headerText = response.settings.headerText ?? 'Hello, world!';
    const animationDuration = response.settings.animationDuration ?? 300;
    const showSplashScreen = response.settings.showSplashScreen ?? true;

    上面代码中,默认值只有在左侧属性值为nullundefined时,才会生效。

    这个运算符的一个目的,就是跟链判断运算符?.配合使用,为nullundefined的值设置默认值。

    const animationDuration = response.settings?.animationDuration ?? 300;

    上面代码中,如果response.settingsnullundefined,或者response.settings.animationDurationnullundefined,就会返回默认值300。也就是说,这一行代码包括了两级属性的判断。

    这个运算符很适合判断函数参数是否赋值:

    function Component(props) {
      const enable = props?.enable ?? true;
      // …
    }

    // 上面代码等同于
    function Component(props) {
      const {
        enable: enable = true,
      } = props;
      // …
    }

    ??有一个运算优先级问题,它与&&||的优先级孰高孰低。现在的规则是,如果多个逻辑运算符一起使用,必须用括号表明优先级,否则会报错。

    // 报错
    lhs && middle ?? rhs
    lhs ?? middle && rhs
    lhs || middle ?? rhs
    lhs ?? middle || rhs

    上面四个表达式都会报错,必须加入表明优先级的括号。

    (lhs && middle) ?? rhs;
    lhs && (middle ?? rhs);

    (lhs ?? middle) && rhs;
    lhs ?? (middle && rhs);

    (lhs || middle) ?? rhs;
    lhs || (middle ?? rhs);

    (lhs ?? middle) || rhs;
    lhs ?? (middle || rhs);

    ES版本更新的福利

    在几个月前的腾讯开发者大会上,有位热心市民向ES开发者请教了这个问题,刚好借这篇文章的话题,在这里分享给大家!

    关于ES版本更新,为什么ES5到ES6是大幅度书籍式的更新,此后版本更新只新增稀少的几个新技术?

    原因:“怕你们学不动!”

    其实,前者的更新方式,要学那么多东西,那么厚的一本天书,会给人一种望而却步的感觉,还没进门就先跪了。

    后者来说,只是几个新技术,可能半天一天的,就能完全掌握并大结局了,收获的成就感会更多更快!

    所以,学习是一辈子的事情,要么接受要么改变,愿好运!!!


    起源地下载网 » ES2021让代码更优美的运算符 (?.) (??)

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元