无论我们开发产品、组件还是工具集,都需要接收外部(上游或用户)输入。通常会有一些结构的约定,比如:
{
info?: {
children?: Array,
keywords?: Array
}
}
这么多的可选,因为我们无法要求用户如此有耐心地创造一堆空结构,但是要用children和keywords怎么办?或者说如何提取更舒适,更满足场景需求?
逻辑运算符
const noChildren = !data.info || !data.info.children;
const noKeywords = !data.info || !data.info.keywords;
const children = noChildren ? [] : data.info.children;
const keywords = noKeywords ? [] : data.info.keywords;
emmm, 结果是符合期望的,但是产生了两个只用了一次的中间变量,改进一下。
const children = data.info && data.info.children || [];
const keywords = data.info && data.info.keywords || [];
但是data.info的书写显得『啰嗦』,更严重的是逻辑运算符的混合降低了可读性。
解构赋值
const {
children = [],
keywords = []
} = data.info || {};
运用解构赋值的默认值写法,很清楚的表达了提取两个属性并赋默认值的想法。而且与逻辑运算符的写法不同的是,解构赋值在=== undefined才会应用默认值,而不是Boolean() === false。
局限是它更适合同层级多属性的提取,对于嵌套层级较深的情况,频繁的默认{}维持解构也破坏可读性。
ES2020运算符
const children = data?.info?.children || [];
const keywords = data?.info?.keywords || [];
?.可以确保访问属性的过程,若中间出现非object属性、属性不存在的状况,会返回undefined。但是『或』运算还是以Boolean() === false判断,改进一下。
const children = data?.info?.children ?? [];
const keywords = data?.info?.keywords ?? [];
??以undefined|null判断,可以作为『严格』的『或』使用。所以,?. ??混合=== undefined|null才会应用默认值。
这种方式适合于嵌套层级较深的情况,但是需要用babel做相关转换,以兼容低版本。
lodash get
const children = _.get(data, 'info.children', []);
const keywords = _.get(data, 'info.keywords', []);
get方法也是在=== undefined才会应用默认值,三个参数的形式也便于理解,但调用的方式适合于嵌套较深的单个属性。
综上
- 逻辑运算符原生兼容性好,可读性不佳。
- 解构赋值和lodash.get都判断undefined,前者适合『集』型,后者适合『链』型,结合可满足复杂需求。
?. ??运算符判断undefined|null,适合『链』型,可作为不引入依赖时,lodash.get的替代,添加babel配置。