Js中.?和??语法(可选链操作符和双问号操作符)

Tips:为啥起这么一个标题呢,因为我自己当时看代码,看到这个语法的时候就感觉有些遗忘,但是又不知道他叫做什么名字,所以只能直接搜索.?和??这样搜索,哈哈哈相信不少人可能跟我一样,不知道他叫做什么名字嘿嘿。

1.可选链操作符(.?)

可选链操作符( ?. )允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。?. 操作符的功能类似于 . 链式操作符,不同之处在于,在引用为空[null]或者 [undefined] 的情况下不会引起错误,该表达式短路返回值是 undefined。与函数调用一起使用时,如果给定的函数不存在,则返回 undefined。

当尝试访问可能不存在的对象属性时,可选链操作符将会使表达式更短、更简明。在探索一个对象的内容时,如果不能确定哪些属性必定存在,可选链操作符也是很有帮助的。

举例

当一个对象的引用或函数可能是undefined或者null时(数组也行),可选链操作符提供了一种方法来简化对被链接对象的值的访问。

以前的操作是这样的:

let name = obj.person && obj.person.name;

使用可选链操作符的操作是这样的:

let name =obj.person?.name;

再来一个比较完整的例子:

我们想获取obj对象中person对象的name属性,

如果我们的obj是如下定义,那么是可以正常取到值得:

let obj = {
   person: {
       name: '张三'
   }
}
/* 首先我们不进行判断直接取值*/
let name = obj.person.name;
console.log("name:", name)

打印输出:

以上是正常情况,那如果我们定义的obj对象中没有person对象

代码如下:

let obj = {
            // person: {
                name: '张三'
            // }
        }
/*没有person对象的情况下不进行判断直接取值*/
let name = obj.person.name;
console.log("name:", name)

 

那么在实际的开发中呢,我们可能不能确定对象中到底有没有想要的属性,这时候我们就需要自行判断,那还是上面的例子,我们加入判断:

let obj = {
            // person: {
                name: '张三'
            // }
        }
/*没有person对象的情况下用常规判断方式取值*/
let name = obj.person && obj.person.name;
console.log("name:", name)

 

以上是常规判断方式,试想一下,如果对象嵌套层级很深,这样写是很麻烦的,所有就有了下面这种判断方式:可选链式操作符:

let obj = {
            // person: {
                name: '张三'
            // }
        }
/*没有person对象的情况下用可选链操作符判断进行取值*/
let name =obj.person?.name;
console.log("name:", name)

 

通过使用 ?. 操作符取代 . 操作符,JavaScript 会在尝试访问 obj.person.name 之前,先隐式地检查并确定 obj.person 既不是 null 也不是 undefined。如果obj.person 是 null 或者 undefined,表达式将会短路计算直接返回 undefined。

 更详细的内容可自行去MDN进行查询哈。

MDN:可选链.?

1.双问好操作符(??)

说到这个得先介绍一下双问好操作符解决了之前哪些操作符的弊端了。

当我们需要判断一个参数是否有值,根据前者然后给他进行赋值,我们第一个想到的肯定是三元运算符boolean ? trueValue : falseValue

如果有一个user对象:

{
  "name": "kaiser",
  "hobby": {
    "sports": {
      "summer": "basketball",
      "winter": "sleep"
    }
  }
}

我们要获取summer这样字段

if (user && user.hobby && user.hobby.sports && user.hobby.sports.summer) {
  return user.hobby.sports.summer
}

好像有点冗长, 这才三层,如果更深的层级就更加刺激了,不对,再来!

try {
  return user.hobby.sports.summer
} catch(e) {
  return undefined
}

这样能一劳永逸解决任何长度的层级,但是还不够优雅。不对,再来!

import get from 'lodash/get'
const result = get(user, 'hobby.sports.summer')

只要任何一个环节出现问题,都会返回一个undefined,但是这需要使用第三方库,不够优雅。不对,再来!

祭出杀手锏,可选链:

return user?.hobby?.sports?.summer

是不是感觉超凡脱俗了很多呢?

上面的例子,如果其中一个属性是null或者undefined,不会报错,而是会返回undefined,比如查询的user对象是下面三种情况:

{
  "hobby": {}
}
{
  "hobby": null
}
{
  "hobby": {
    "sports": "basketball"
  }
}

那么得到的返回值都是undefined。

可选链其他写法:

obj?.prop // 对象的点号判断 user?.hobby?.sports
obj?.[expr] // 对象的方括号判断 user?.['hobby']?.['sport']
arr?.[index] // 数组判断 userList?.[12]?.name
func?.(args) // 方法判断 user?.run?.('1hours')