需求说明
获取对象类型中深层嵌套的value值
比如我们定义一个对象类型:var object = {
a: 1,
b: '2',
c: [3, '4', [5], {d: 6}],
e: {f: 7}
}
如果要取到d的值我们需要object.c[3].d,如果这个对象数据是后台返回的值为:
var object = {
a: 1,
b: '2',
c: [3, '4', undefined, null],
e: undefined
}
此时按照上述的方法进行取值肯定会报错,这个时候我们就需要使用多重条件判断来解决这个问题:
var value = object && object.c && object.c[3] && object.c[3].d
很明显,这种写法太啰嗦,于是我们想到了使用可选链
可选链的使用
使用MDN介绍的可选链方式我们只需要
var value = object?.c?[3]?.d
这样写确实简洁了太多,但是从MDN上可以得知这个方式浏览器兼容性不太好,因此我们需要安装Babel插件(@babel/plugin-proposal-optional-chaining)从编译时角度来解决可选链的问题。
还有其他的解决方式是使用safeGet或者lodash库里的get函数,但是这些实现起来都不够优雅, 有没有更好的解决方式呢?
从运行时的角度解决取值问题
这里我们可以使用safedata-get这个库
首先,先安装这个库:
npm install safedata-get
然后在代码中我们可以这样进行取值:
import safeData from 'safedata-get';
var object = {
a: 1,
b: '2',
c: [3, '4', undefined, null],
e: undefined
}
var safeObject = safeData(object);
var value = safeObject.c[3].d(); // undefined
这样,即使中间出现了undefined取值也不会报错,如果我们需要给undefined一个兜底值,可以这样:
var value = safeObject.c[3].d('hello'); // 'hello'
safeData函数即使给undefined,null等空值进行包裹也不会报错:
var safeUndefined = safeData(undefined);
var safeNull = safeData(null);
console.log(safeUndefined.hello.world.juejin.nihao()) // undefined
console.log(safeNull.hello.world.juejin.nihao()) // null
safeData能够完整保留对象的this:
var object = {
a: 'hello',
sayHello() {
return this.a + ' juejin!'
}
}
var safeObject = safeData(object);
console.log(object.sayHello()) //hello juejin!
console.log(safeObject.sayHello()()) //hello juejin!
从原理角度,safeData是如何实现的呢? 其实safeData是基于Proxy的getter来实现的, 具体源码可以查看这个库的源码,只有短短几十行。
总结
今天简单介绍了可选链相关的使用以及safedata-get这个库的使用方式,喜欢的话赶快用起来吧!