可选链操作符(?.)——开发必备神器
它的出生
随着现在前后端分离的推进越来越快,现在的日常开发前端往往是自己不需要去数据库操作数据了,只需要通过调用API就可以进行数据获取。这虽然极大的方便了我们的开发,但是随之而来也会伴生各种各样的新问题,比如数据的层次嵌套过深、数据不单一等等一系列原因,使得我们往往需要做很多的逻辑判断。
比如我们在后端拿出了people的数据,想去直接获取它的家庭人口,如果像下面这样子直接获取,可能会有时候能够拿到,有时候因为场景变化就会缺少这个字段,获得ERROR大奖章一枚!
const people = {} // 假设这是后端数据
console.log(people.family.numbers);
js中直接获取不存在的数据是会引发异常,导致整个进程done掉,但是因为一个小小的数据没有导致整个进程done掉很明显不是我们想要的结果,那么我们就要进行一下控制了。在这里解决办法大致分为两种,一种是借助第三方库,第二种就说自己手动拦截了。
-
第三方库
在这里我们直接拿lodash来使用,lodash我们要获取一个对象下的数据,往往会使用getter方法
_.get('people','family.numbers')
在lodash中如果存在我们要获取的
key
,就会返回该key
下的value
,即我们想要的numbers
,如果不存在,就返回空(顺便我们具体看看他背后做了哪些操作吧)//get.js function _get(data,f){ if(f.substr) f = f.split(/\.|\\|\//); if(f.length && data){ return _get(data[f.shift()],f) }else if(!f.length && data){ return data }else { return ""; } } export default function(target,path,defaultValue){ return _get(target,path,defaultValue); }
-
原生自己js手写
自己手写进行拦截其思路也是极其简单,就是逐层向下判断有没有就行了。
console.log(people && people.family && people.family.numbers);
当进行逐个判断的时候,一个不存在就会返回undefined,从而避免ERROR,但是相比之下,如果不依赖第三方库的时候,自己写就显得极其复杂了。假设这数据结构的深度不是三层,是5层,10层呢?那是不是就显得极其复杂了?
这是在这个背景之下,我们今天的猪脚——可选操作符?.
就出来了!那么使用可选操作符我们又要怎么操作呢?
我们只需在需要判断的的地方使用它就好了呀!
console.log(people?.family?.numbers); // undefined
就是这么的简单!!!这是这么粗暴!!!只要在需要判断的地方前面,多加一个?就欧了
这么实用的操作,确定不学习吗?
基础使用
官方定义MDN文档:可选链操作符( ?. )允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。?. 操作符的功能类似于 . 链式操作符,不同之处在于,在引用为空(nullish ) (null 或者 undefined) 的情况下不会引起错误,该表达式短路返回值是 undefined。与函数调用一起使用时,如果给定的函数不存在,则返回 undefined。
当尝试访问可能不存在的对象属性时,可选链操作符将会使表达式更短、更简明。在探索一个对象的内容时,如果不能确定哪些属性必定存在,可选链操作符也是很有帮助的。
可选操作符的基础使用其实是极其简单的,就是在可能会因为缺乏字段引起error的地方加上即可。怎么确定从哪里开始会引发这个error呢?
我们还是从那个有(jian)趣(lou)的后端数据讲起吧
const people = {} // 假设这是后端数据
console.log(people); // {}
console.log(people.family); // undefined
console.log(people.family.number); // ERROR
由输出可以看到,其实js本身还是有一定的容错机制的,所以我们只需要在可能会触发容错机制的地方,加上即可!
虽然使用可选操作符很简单,但是还是有很多注意事项的
-
可选操作符前面的变量必须声明!如果该操作符前面的变量未声明,那么就会引发error
-
不可过度使用,我们只需要在可能会引发error的地方使用就好,?.虽好,可不要贪多哦(官方建议,为啥俺也不知道)
-
当遇见
null
或者undefined
就结束(也就是短路) -
可选链不能用于赋值,只能用于判断是否会短路,会短路就返回undefined,否则就返回该
key
的值(如果想赋默认值,就要使用它的兄弟??
)
它的兄弟——空值合并操作符(??)
上文说到,可选操作符是不可以进行赋值操作的,但是它的兄弟可以呀😎,毕竟葫芦娃能吐水的就不能吐火呢
过去
在可选操作符和空值合并操作符出现之前,我们要判断一个一个属性是否存在,存在的时候取出它的值,,不存在的时候赋默认值,我们可能要像下面一样写一长串:
console.log(people && people.family && people.family.numbers || '不存在');
往往是极其长而麻烦的,但是现在不一样了!
现在
我们只需要将他们两兄弟配合使用即可:
console.log(people.family?.number ?? '不存在');
只有当前面为null或者undefined的时候,会进行空值合并操作,就是赋予后面设定的默认值。
进阶
前面讲了那么多,都是很基础的用法,接下来让我们一起学习一下骚操作吧!
在js中,对象里面可以包含的东西是很多很多的,所以?.
也不仅仅使用在简简单单的判断操作上。他还可以应用到数组、函数等等一系列操作上
语法:
obj?.prop
obj?.[expr]
arr?.[index]
func?.(args)
开始的两个简单的我们已经学习完了,接下来看看数组和函数的吧!
数组
其实arr?.[index]
从表达式就可以很清晰的知道,就是获取arr[index]
元素。如下:
let arr = [1, 2, 3];
console.log(arr?.[5]); // undefined
或许小伙伴们会觉得这个可能很小儿科,就算不用也没问呀,但是如果是下面这种情况呢?
let demo = {
}
console.log(demo.a[1]); // ERROR
console.log(demo.a?.[1]); // undefined
如果不进行判断不就error了吗?判断那么又要像开篇一样进行一系列枯燥繁琐的判断,但是使用?.
不就可以很快速解决这个问题了?
函数
我们要获取的,往往是不仅仅只限于数据,有时候我们可能获取一些API,但是如果不存在对应的API,照样会引发异常,在这里,照样有解决办法!
const demo1 = {
func() {
console.log('欸嘿,就不报错!');
}
}
const demo2 = {
}
demo1.func(); // 欸嘿,就不报错!
demo2.func(); // TypeError: demo2.func is not a function
我们使用可选操作符,就可以完美的避免这个error
const demo1 = {
func() {
console.log('欸嘿,就不报错!');
}
}
const demo2 = {
}
demo1.func?.(); // 欸嘿,就不报错!
demo2.func?.(); //
但是在这里有一个需要大家注意的点,当判断到存在和函数同名的非函数属性时,会引发异常
const demo1 = {
func() {
console.log('欸嘿,就不报错!');
}
}
const demo2 = {
func = 'demo'
}
demo2.func?.(); //
获取很多小伙伴会觉得在数组和函数的应用上会很别扭,但是大家结合一下js的执行机制去理解,就会明白为何要这么写以及为何存在同名非函数会进行报错了
支持情况
其实?.
操作符并不是在js独有,目前在C#,Swift都有,而且TS也加入该新特性。在node.js需要升级到14.0以上才支持(但是一般都会使用Babel进行转译,所以完全不用担心啦!)
浏览器支持情况
我是江河,前端实习生一枚,文章如有不正之处,敬请斧正!
面对新事物,我们要勇于拥抱,只有不断接受新事物,将新特性为我们所用,才能不断前进,不断超越!
转载自:https://juejin.cn/post/6983611335690944549