考虑我有一个像这样的对象:
Obj.Boo.Foo.Zoo
好的,现在如果我想确定它zoo
有一个值而不是空的,我应该这样做:
if(Obj != null && Obj.Boo != null && Obj.Boo.Foo != null && Obj.Boo.Foo.Zoo != null) {
//blah blah
}
如果在 之后我有更多的嵌套对象Zoo
,我应该扩展if
并且代码变得有点格式错误。
有没有更好的方法来处理这种情况?
考虑我有一个像这样的对象:
Obj.Boo.Foo.Zoo
好的,现在如果我想确定它zoo
有一个值而不是空的,我应该这样做:
if(Obj != null && Obj.Boo != null && Obj.Boo.Foo != null && Obj.Boo.Foo.Zoo != null) {
//blah blah
}
如果在 之后我有更多的嵌套对象Zoo
,我应该扩展if
并且代码变得有点格式错误。
有没有更好的方法来处理这种情况?
我保留了一个小功能,我会chainGet(obj, chain, default)
在这样的情况下调用:
function chainGet(obj, chain, dflt) {
if (typeof chain === "string")
chain = chain.split(".");
var result = obj;
for (var i = 0; i < chain.length; i += 1) {
if (result === undefined)
break;
result = result[chain[i]];
}
return result === undefined? dflt : result;
}
例如:
> chainGet({ foo: 42 }, "foo")
42
> chainGet({ foo: 42 }, "bar", "x")
'x'
> chainGet({ foo: { bar: 42 }}), "foo.bar")
42
这甚至适用于数组:
> chainGet([{ foo: [42] }], [0, "foo", 0])
42
当然,长链的点状访问是一种代码味道,所以在使用它们时应该小心……但有时你必须这样做;)
如果您真的不需要处理这种情况,一个不好的做法是尝试在 try catch 语句中访问 Object
try{
// access Obj.Boo.Foo.Zoo
}
catch{
// catch a NullReferenceException
}
更好的方法是修改您的 getter 和 setter,以便父对象在您尝试访问子对象及其 null 时抛出合适的异常或处理此异常。在这种情况下,检查第一个对象就足够了。
它可以在不使用函数的情况下实现。捷径方法可能是 -
if(((((Obj || {}).Boo || {}).Foo || {}).Zoo || {}) != {}) {
// Zoo has a value and not empty
}
或者 ES6 的方式——
const checkNull = (keys, Object) =>
keys.reduce((Obj, o) =>
(Obj && Obj[o]) ? Obj[o] : null, Object)
console.log(checkNull(['Boo', 'Foo', Zoo], Obj))
// [Value of Zoo]
console.log(checkNull(['Boo', 'Foo1', Zoo], Obj))
// null