本文主要介绍ES2020引入的两个特殊符号在开发中的使用。
可选链操作符(Optional Chaining)
操作符:?
作用
该操作符(?)会检查操作符左边的值是否为 null 或 undefined。如果是,这个表达式就终止然后返回 undefined。否则,这个表达式继续执行检查通过!
测试
var a=null, b;
console.log(a.toString()) // 报错:Uncaught TypeError: Cannot read property 'toString' of null
console.log(a?.toString()) // undefined
console.log(b.toString()) // 报错:Uncaught TypeError: Cannot read property 'toString' of null
console.log(b?.toString()) // undefined
情景
无论是B端产品还是C端产品,下拉选框都是一个常见的模块。我们来完成下图所示的功能。

import React, { useState, useEffect } from 'react'
import { get } from '../../utils/request'
import { Select, Card } from 'antd'
const { Option } = Select
const URL = '/api/common/allcities'
function Demo() {
const [cities, setCities] = useState([])
const [value, setValue] = useState()
useEffect(() => {
async function getCities() {
const data = await get(URL)()
setCities(data.allcities)
}
getCities()
}, [])
console.log(cities, value)
return (
<Card>
<span>城市:</span>
<Select
labelInValue
value={value}
placeholder="请选择城市"
onChange={(value) => setValue(value)}
style={{ width: 256 }}
>
{cities.map((item) => <Option key={item.cityId}>{item.name}</Option>)}
</Select>
<div style={{ marginTop: 20 }}>
已选择城市:{value.label}
</div>
</Card>
)
}
export default Demo
但是运行起来,就报错了。

分析
由于接口返回数据的不可控性或者数据类型变化等不可控因素,我们不得不加入一些容错代码来避免模块报错。
第13行:
const data = (await get(URL)()) || {} //避免接口返回值为null的时候,第14行报错
第29行:
cities && cities.length &&cities.map((item) => <Option key={item.cityId}>{item.name}</Option>) //cities可能为null
第33行:
已选择城市:{value ? value.label : ''} //value在初始化的时候值为null
所以以前,我写出来的代码是这样的:
import React, { useState, useEffect } from 'react'
import { get } from '../../utils/request'
import { Select, Card } from 'antd'
const { Option } = Select
const URL = '/api/common/allcities'
function Demo() {
const [cities, setCities] = useState([])
const [value, setValue] = useState()
useEffect(() => {
async function getCities() {
const data = (await get(URL)()) || {}
setCities(data.allcities)
}
getCities()
}, [])
console.log(cities, value)
return (
<Card>
<span>城市:</span>
<Select
labelInValue
value={value}
placeholder="请选择城市"
onChange={(value) => setValue(value)}
style={{ width: 256 }}
>
{cities &&cities.length &&
cities.map((item) => <Option key={item.cityId}>{item.name}</Option>)}
</Select>
<div style={{ marginTop: 20 }}>
已选择城市:{value ? value.label : ''}
</div>
</Card>
)
}
export default Demo
我们有各种容错的处理方式,但是容错带来的结果就是代码不够干净。 当ES2020到来之后,我们可以这样写:
import React, { useState, useEffect } from 'react'
import { get } from '../../utils/request'
import { Select, Card } from 'antd'
const { Option } = Select
const URL = '/api/common/allcities'
function Demo() {
const [cities, setCities] = useState([])
const [value, setValue] = useState()
useEffect(() => {
async function getCities() {
const data = await get(URL)()
setCities(data?.allcities)
}
getCities()
}, [])
console.log(cities, value)
return (
<Card>
<span>城市:</span>
<Select
labelInValue
value={value}
placeholder="请选择城市"
onChange={(value) => setValue(value)}
style={{ width: 256 }}
>
{cities?.map((item) => (
<Option key={item.cityId}>{item.name}</Option>
))}
</Select>
<div style={{ marginTop: 20 }}>已选择城市:{value?.label}</div>
</Card>
)
}
export default Demo
在第13行、29行、33行,仅仅引入一个“?”操作符,就代替了很多繁琐的容错处理,真香!
空位合并运算符(Nullish coalescing Operator)
操作符:??
作用
我们知道无论是三元运算符(?:)还是与(&&)、或(||)运算符,都是判断作为为true和false。而空位符(??)判断的是运算符左侧值是否为空(undefined 或 null),为空则返回其右侧值。
测试
var a=null, b=false;
console.log(a??'默认值') //"默认值"
console.log(b??'测试') // false
情景
产品大大要求做一个统计表格,其中得分栏如果没有值,展示中横线。

我以前是这样做的
import React from 'react'
import { Table, Card } from 'antd'
import { isNumber } from 'lodash'
const mockData = [
{ name: '张三', score: 10, key: 1 },
{ name: '李四', score: 0, key: 2 },
{ name: '王五', key: 3 },
]
function Demo() {
const columns = [
{ title: '姓名', dataIndex: 'name' },
{
title: '得分',
dataIndex: 'score',
render: (text, record) => {
return isNumber(record.score) ? record.score : '-'
},
},
]
console.log(mockData)
return (
<Card>
<Table
bordered
pagination={false}
dataSource={mockData}
columns={columns}
/>
</Card>
)
}
export default Demo
这里引入了lodash的isNumber方法判断了score是否为数字,如果是数字返回score,否则返回中横线。之所以用isNumber方法判断,而不是简单的写作return record.score||'-'
,是因为存在score为0的时候无法展示数字0,而被展示为中横线。
下面我们用ES2020的空位符来优化代码
const columns = [
{ title: '姓名', dataIndex: 'name' },
{
title: '得分',
dataIndex: 'score',
render: (text, record) => {
return record.score ?? '-'
},
},
]
不必引用lodash,代码简单优雅。 是不是更香了(^▽^)
结语
ES2020还有很多好用的功能!大胆去尝试吧,少年们~