操作符

200 阅读3分钟

这是我参与「掘金日新计划 · 8 月更文挑战」的第2天,点击查看活动详情

可选链操作符(?.)

允许读取位于连接对象链深处的属性的值,而不必明确链中的每个引用是否有效。可选链操作符可以连用。

?.操作符类似.链式操作符,不同之处在于如果引用为null或undefined链式操作符会直接报错,但可选链操作符不会报错,直接返回undefined。

当对象属性可能不存在时,需要使用可选链操作符,比如在react渲染dom的时候,我们可能还没有获取到接口中的数据,渲染视图的时候,我们就可以使用可选链操作符。

语法

obj?.prop
obj?.[expr]
arr?.[index]
func?.(args)

举个栗子

const obj = {
    a: 1,
    name: 'text'
    c: null,
    d: undefined
}

console.log(obj.b?.name) // undefined
console.log(obj.b.name) // "TypeError: Cannot read properties of undefined (reading 'name')
console.log(obj.c?.name) // undefined
console.log(obj.d?.name) // undefined

同样也可以使用于函数调用,比如中我工作中经常用的swiper的slide函数,如果在useEffect中使用,会出现dom加载还没有完成slide函数就执行的问题,我们就可以在slide已经绑定在实例时再执行。

mySwiper.slide?.()

// 等价于
(mySwiper.slide === null || mySwiper.slide === undefined) ? undefined : mySwiper.slide()

如果slide本身不是一个函数则还是会报错slide is not a function

如果没有可选链操作符,我们往往采取这样的方式避免报错。但是如果对象嵌套的层级很深,表达式就会太长。

obj.b && obj.b.name
obj.b && obj.b.name && obj.b.name.first

使用可选链表达式会在访问属性时,隐式的判断可选链前的表达式不为null或者undefined,如果是则会返回undefined。

可选链操作符是短路计算,比如obj为null,后面的就不会执行。

let obj = null
let a = 1
let b = obj?.[a++]

console.log(a) // 1

不可用作赋值

let obj = {}
let a = obj?.name = 'a'
console.log(a) // "SyntaxError: Invalid left-hand side in assignment

空值合并操作符(??)

空值合并操作符(??)是一个逻辑操作符,当左侧的操作数为 null 或者 undefined 时,返回其右侧操作数,否则返回左侧操作数。和可选链操作符一致左边不为null或undefined右边不执行

空值合并操作符可以和可选链操作符一起使用,在返回undefined时,给一个默认值。 很多可能会有疑问,使用逻辑或操作符不是效果一样吗。

逻辑或操作符会在左侧为假值时返回右侧值,如果使用||设置默认值,''和0都是假值也会返回默认值。

const obj = {
    name: 'text'
}

let a = obj.a?.b ?? '默认值'
console.log(a) // 默认值

const a = 0 ?? 1
const b = 0 || 1

console.log(a) // 0
console.log(b) // 1

可以用作赋值

let obj = {}
let a = obj?.name ?? '默认值'
console.log(a) // 默认值

??不可直接与||和&&使用,因为它们的优先级没有明确的定义,如果通过()增加优先级即可使用。

null || undefined ?? "foo"; // 抛出 SyntaxError
(null || undefined ) ?? "foo"; // 返回 "foo"

逻辑或(||)

当且仅当其中一个或多个操作数为真时为真。它通常与布尔值一起使用返回一个布尔值。如果和非布尔值一起使用,则返回非布尔值

在第一个值执行为真时返回第一个,否则返回第二个值。 null、NaN、undefined、''、0都可以转换为false

function A(){ console.log('called A'); return false; }
function B(){ console.log('called B'); return true; }

console.log( A() || B() );
// "called A" "called B" true

console.log( B() || A() );
// "called B" true

a = 'Cat' || 'Dog' // "Cat"
b = false || varObject // varObject

逻辑与(&&)

&& 优先级高于 || 当且仅当所以操作数为真时为真。它通常与布尔值一起使用返回一个布尔值。如果和非布尔值一起使用,则返回非布尔值

在第一个值执行为真时返回第二个,否则返回第一个值。

function A(){ console.log('called A'); return false; }
function B(){ console.log('called B'); return true; }

console.log( A() && B() ); // called A false
console.log( B() && A() ); 
// called B called A false

a = 'Cat' && 'Dog' // "Dog"
b = false && varObject // false