24.什么?你还不知道JavaScript的新特性可选链?.,你睡得着觉?

可选链"?."

可选链?.JavaScript新添加的一个语法,是一种访问嵌套对象属性的安全方式,可以避免出现属性不存在错误。

前言

在使用对象编程的时候,我们经常会遇到属性不存在的问题。例如我们定义一个空的对象,然后访问这个对象的属性:

let people = {
    
    };//定义一个空的对象
console.log(people.name);//name 属性不存在 undefine

毫无疑问,以上代码将输出undefined。问题在于,如果我们想通过name属性,访问surname属性:

let people={
    
    };
console.log(people.name.surname);//访问名称中的姓

此时,就会发生意料之中的错误:

> Error: undefined is not an object (evaluating 'people.name.surname')

出现这种错误的原因在于,people.name本身就是一个undefined的值,而以上代码尝试获取一个undefined对象的属性,显然是不合适的。
在实际的编程场景中,我们经常会遇到对象相会嵌套的情况,例如:China.Beijing.Fengtai.Shilipu...,在这种多层级的嵌套访问情况下,如果其中任意一环的值是null或者undefined,就会引发上述异常。

而我们希望的结果是,不论是末级属性还是中间对象不存在,都统一返回undefined。实际上,使用之前的知识同样可以做到这点,不过稍显繁琐。
例如,我们可以使用三目运算符:

let people = {
    
    };
let surname = people.name?people.name.surname?people.name.surname.firstCharacter:null:null;

看起来还不错,但是试想一下,如果存在四级甚至多层次的属性,需要嵌套多少层三目运算符!这太可怕了。
还有一种稍微优雅一点的方法&&

let people = {
    
    };
let surname = people.name && people.name.surname && people.name.surname.firstCharacter;

利用&&链返回第一个假值的特性,可以相当优雅的实现多层级对象属性访问。但是,这并不是最优雅的方式,people.name已经被我们写了好多遍,如果层级更多,我们还要写更多遍。
这就是?.语法被加入的原因。

可选链使用

可选链?.的作用是,如果可选链?.前面的对象是null或者undefined,那么他就会停止执行并返回 undefined

本文设定:如果一个值是 null 或者 undefined,那么他就是"不存在的",否则就是"存在的"。

举个例子:

obj?.prop;

以上代码结果的计算方式为:

  1. 如果 obj 存在,那么返回obj.prop
  2. 如果 obj 不存在,直接返回undefined;

此时,如果我们访问深层次的属性,就可以采用如下格式:

let people = {
    
    };
let lastCharacter = people?.name?.surname?.lastCharacter;

lastCharacter最终的结果就是undefined
这样,我们就以最优雅的方式实现了可能存在错误的访问方式,保证程序最坏的结果就是返回 undefined

我们还可以对值为null的对象使用,甚至直接对null使用null?.name同样不会出现程序异常:

let user = null;
console.log(user?.name);
console.log(null?.name);

代码执行结果为:

> undefined
> undefined

说明:
可选链?.是对其前面的对象生效的,例如:user.name?.surname.firstCharacter中,只对name属性负责。
如果surnameuser不存在,那么同样会报错。

过度使用可选链不可取
有些童鞋肯定就会认为?..要好用,毕竟不会那么容易报错了,不如使用?.完全代替.访问属性吧?
这种思想是错误的,在访问多层级嵌套属性时,使用.可以及时的发现程序中的错误,例如我么在开发过程中,访问user.name.surname时发生了错误,那么我们就可以早早的发现这个错误,然后评估这个错误的合理性,从而改进我们的代码。
然是,如果大量使用、甚至全盘使用?.就会抑制错误的爆发,消除一些本不该消除的错误,导致程序出现莫名其妙的错误,而且很难通过日志信息定位错误的位置。
我们要改变"报错是邪恶的"这种观念,实际上,报错可以告诉我们错误的位置和错误的信息,帮助我们编写更加优质的代码。

可选链同样会出错,例如我们对一个没有声明的变量使用,例如obj?.name中的obj还没有声明,那就会报错。

可选链的短路效应及其用法

?.对左侧的值负责,如果左侧的值不存在,立即停止执行,右边的内容不会执行。这就和||&&的短路效应相似,我们可以利用这种特性调用方法。
举个例子:

let user = {
    
    
    hello:function(){
    
    console.log('hello');}
}
user?.hello();//执行 hello 函数,输出hello
user = null;
user?.hello();//不会执行 hello 函数

可选链的变体

可选链?.不是运算符,而是一个长的奇怪的语法结构,他可以和其他函数和方括号一起使用。

  • 使用可选链调用一个可能不存在的函数?.()
let user = {
    
    
    hello:function(){
    
    console.log('hello');}
};
user.hello?.();//执行 hello 函数
let dog = {
    
    };
dog.hello?.();//什么都没有发生

以上代码中,?.会判断前面的属性是否存在,如果存在,则使用后面的小括号调用函数,如果不存在,立即停止执行,什么都没有发生。如果我们使用console.log(dog.hello?.());输出最后一行代码,会发现输出了一个undefined

  • ?.[]访问属性
    在访问对象属性时,如果不使用.,我们还可以选择使用[],如果配合可选链,就能安全的访问一个可能不存在的属性:
let user = {
    
     name: 'xiaoming', };
let dog = {
    
    };
console.log(user?.['name']);//xiaoming
console.log(dog?.['name']);//undefined

虽然看起来很奇怪,但是仍然可以正确的执行。

  • 删除可能不存在的属性
    我们还可以结合delete删除一个可能不存在的属性:
delete user?.name;

如果user.name属性不存在,同样不会出错。

总结

可选链的三种使用方式:

  1. obj?.prop?.prop可以安全的访问可能不存在的属性,最坏的结果就是返回undefined
  2. obj.method?.()可以安全的调用一个可能不存在的方法;
  3. obj?.[prop]安全的访问一个可能不存在的属性;
  4. obj?.mentod()安全的访问一个可能不存在对象的方法;

猜你喜欢

转载自blog.csdn.net/weixin_43302112/article/details/124685282
今日推荐