Optional Chaining for JavaScript

260 阅读2分钟

我们在访问对象深处属性(或方法)或者是对不确定对象属性(或方法)时, 以前我们是这样做的:

// part1 if (low版本)
if (obj) {
  if (obj.a) {
    obj.a()
  }
}
// part1 进化版
obj && obj.a && obj.a()
// dom元素
var checkEle = document.querySelector('#ele')
var inner = checkEle ? checkEle.innerText : undefined
var _inner = checkEle && checkEle.innerText
// 处理服务端返回数据
fetch('xxx?xx=xx').then(responese => {
  // 当然这个地方我们可以解构
  const { error, data: { count } } = responese
  error === 0 ? count ? this.count = count : undefined : this.$toast('xxxxx')
})
// react
render() {
  const { artical } = this.props
  return (
    <>
      <div>xxxxx</div>
      <span>{ artical ? artical.length ? '您已阅读完成' : '' : '当前文章加载中' }</span>
    </>
  )
}

这里有人要问了,非要做这种判断嘛~我觉得答案是肯定的,因为你在访问有一定深度的对象中的方法或者属性的时候,很容易因为上一级是undefined而导致你后续逻辑无法按照正常的逻辑进行。比如下面的错误:

option-error

这个时候,就要把我今天要介绍的optional Chaining请出来啦~


正文

介绍(其实是我自己编的)

解决处理访问一定深度对象的属性或方法为空值的一个运算符(笔者自己编的~我个人觉得是一个运算符,23333)

所处阶段

stage-2
不过babel7已经提供了对应的插件可以使用这个新特性了,在下面我也会告诉大家具体的用法。

句法(大概可以成为句法, 其实大概就是简单的使用方法)

optional chaining : ?.(重要的事情所三遍: 是?., ?., ?.。不是?, ?, ?。)
通过改写上面的一些例子我们来感受一下:

// part1 if (low版本)
if (obj) {
  if (obj.a) {
    obj.a()
  }
}
// 使用 optional chaining
obj?.a?.()
// dom元素
var checkEle = document.querySelector('#ele')
var inner = checkEle ? checkEle.innerText : undefined
var _inner = checkEle && checkEle.innerText
// 使用 optional chaining
var inner = checkEle?.innerText
// 处理服务端返回数据
fetch('xxx?xx=xx').then(responese => {
  // 当然这个地方我们可以解构
  const { error, data: { count } } = responese
  error === 0 ? count ? this.count = count.length : undefined : this.$toast('xxxxx')
  // 使用 optional chaining
  error === 0 ? (this.count = count?.length) : this.$toast('xxxxx')
})

babel编译结果

// 源代码
const optionChainObj = {
  step1: {
    step2: {
      step3: 'step3'
    },
    step4() {
      console.log(123)
    }
  }
}
// babel编译后
"use strict";
var r, o, u = {
    step1: {
        step2: {
            step3: "step3"
        },
        step4: function() {
            console.log(123)
        }
    }
};
null == u || null === (r = u.step1) || void 0 === r || null === (o = r.step4) || void 0 === o || o.call(r);
// 备注: void 0 的结果是undefined

我们看上述的编译代码,其实是插件内部帮我们扩展了我们原来需要写的一些代码,但是整体上会让我们的代码更加的简洁并且可读性更高一些~

适用场景

obj?.prop       // optional static property access
obj?.[expr]     // optional dynamic property access
func?.(...args) // optional function or method call
  • 不确定属性访问(上面的栗子就是哦)
  • 可衔接运算符或者表达式使用
// 源代码
var testOptions = [ 1, 2, 3 ]
var x = 0
var curr = testOptions?.[++x]
console.log(curr)
// babel 编译过后
var c = [1, 2, 3]
      , f = 0
      , a = null == c ? void 0 : c[++f];
console.log(a);
  • 不确定函数或者方法
// 源码
var fuc = (name = '') => { console.log(name) }
fuc?.('ok')
// babel 编译过后
var s = function() {
      var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "";
      console.log(e)
  };
null == s || s("ok")

现在想用怎么办?

  • 首先安装babel
# 注意我们需要使用babel7.0及以上版本
npm install --save-dev @babel/core @babel/cli
  • 安装babel-plugin-syntax-optional-chaining插件
npm install --save-dev @babel/plugin-syntax-optional-chaining
  • 配置.babelrc
{
  "plugins": ["@babel/plugin-syntax-optional-chaining"]
}

现在,你可以愉快的使用optional chaining啦~~


optional chaining github github.com/tc39/propos…


tip
切勿花式秀技巧,导致自己代码可读性下降。


你也可以关注我的公众号