我经常发现自己必须先构建长链,然后才能映射到数组上以检查是否已定义:
this.props.photos &&
this.props.photos.activePhotos &&
this.props.photos.activePhotos.map(...
如果未定义this.props.photos &&
和this.props.photos.activePhotos.length &&
,而photos
或activePhotos
未定义,我的整个应用程序将崩溃。
有没有一种方法可以检查这些道具而不必检查我的最终物品的每个父对象/数组?
答案 0 :(得分:7)
另一种选择是在解构道具时使用默认值:
const { photos = {} } = this.props
const { activePhotos = [] } = photos
activePhotos.map(/* */)
在这种情况下,如果未定义photos
,它将被一个空对象代替。尝试从中取出activePhotos
会得到一个空数组,无论如何都可以在其上进行映射。
答案 1 :(得分:4)
我猜您指的是可选链接,这是TC39的第1阶段
答案 2 :(得分:1)
根据嵌套的级别,我看到了两种可能的方法。
您可以使用lodash.get。
只有在activePhotos
存在的情况下,这里是如何渲染它们的方法:
// Please note how do we pass default `[]` as third parameter
// in order to not break the `.map` function
_.get(this.props, 'photos.activePhotos', []).map(...)
如果您只想检查深度嵌套的专家,则可以使用lodash.has
方法:
// Will return `true` / `false`
_.has(this.props, 'photos.activePhotos')
只需使用本机ES6解构分配+默认值功能。
const { photos = {} } = this.props
const { activePhotos = [] } = photos
// Now you can safely map over the `activePhotos`
activePhotos.map(...)
答案 3 :(得分:0)
有没有一种方法可以检查这些道具而不必检查每个 最终项目的父对象/数组?
通常,不会。
目前尚不清楚为什么在问题代码处检查了.length
的电位。
如果目标是减少代码长度,则可以使用JSON.stringify()
和RegExp
if (/"activePhotos":\[.*\]/.test(JSON.stringify(this.props))) // do stuff
或者如果首选方法是使用AND
运算符
/"activePhotos":\[.*\]/.test(JSON.stringify(this.props)) && // do stuff
答案 4 :(得分:0)
undefsafe 是一个足够好的库可供使用。还有很多其他可用的库。
使用方法的简单示例
var object = {
a: {
b: {
c: 1,
d: [1,2,3],
e: 'remy'
}
}
};
console.log(undefsafe(object, 'a.b.e')); // "remy"
console.log(undefsafe(object, 'a.b.not.found')); // undefined
答案 5 :(得分:-1)
这是具有默认值返回的功能性方法,用于可选链接。该方法使用Maybe
单子和Proxy
。
wrap()
函数用于包装可以安全访问任何属性的对象。在内部,wrap
在对象周围创建代理,并使用Maybe包装器管理缺失值。在链的最后,您可以通过将getOrElse(default)
与默认值链接来解开该值,默认值将在属性访问失败时返回:
class Maybe {
constructor(value) {
this.__value = value;
}
static of(value){
if (value instanceof Maybe) return value;
return new Maybe(value);
}
getOrElse(elseVal) {
return this.isNothing() ? elseVal : this.__value;
}
isNothing() {
return this.__value === null || this.__value === undefined;
}
map(fn) {
return this.isNothing()
? Maybe.of(null)
: Maybe.of(fn(this.__value));
}
}
function wrap(obj) {
function fix(object, property) {
const value = object[property];
return typeof value === 'function' ? value.bind(object) : value;
}
return new Proxy(Maybe.of(obj), {
get: function(target, property) {
if (property in target) {
return fix(target, property);
} else {
return wrap(target.map(val => fix(val, property)));
}
}
});
}
const obj = { a: 1, b: { c: [4, 1, 2] }, c: () => 'yes' };
console.log(wrap(obj).a.getOrElse(null)) // returns 1
console.log(wrap(obj).a.b.c.d.e.f.getOrElse(null)) // returns null
console.log(wrap(obj).b.c.getOrElse([])) // returns [4, 1, 2]
console.log(wrap(obj).b.c[0].getOrElse(null)) // returns 4
console.log(wrap(obj).b.c[100].getOrElse(-1)) // out-of-bounds index: returns -1
console.log(wrap(obj).c.getOrElse(() => 'no')()) // returns 'yes'
console.log(wrap(obj).d.getOrElse(() => 'no')()) // returns 'no'
请参阅this blog post和this link,以获取有关Maybe monad和代理使用的更多信息。