如何避免;“未定义”的性质;JavaScript中没有大if语句时出错?

如何避免;“未定义”的性质;JavaScript中没有大if语句时出错?,javascript,jquery,Javascript,Jquery,我通常会发现自己在处理这样的深部物体: var x = { y: { z: { a:true } } } 在代码的某个地方: if( x.y.z.a === true ){ //do something } 在某些情况下,任何x、y、z变量都可能未定义,在这种情况下,您将得到“无法读取未定义的属性*” 潜在的解决方案是: if( x && x.y && x.y.z && x.y.z.a === true

我通常会发现自己在处理这样的深部物体:

var x = {
  y: {
    z: {
      a:true
    }
  }
}
在代码的某个地方:

if( x.y.z.a === true ){
  //do something
}
在某些情况下,任何x、y、z变量都可能未定义,在这种情况下,您将得到“无法读取未定义的属性*”

潜在的解决方案是:

if( x && x.y && x.y.z && x.y.z.a === true ){
  //do something
}
jsfiddle:


但是有更简单/更短的方法吗?内联解决方案(不使用特殊函数)将非常好。谢谢。

不,你已经找到了正确的方法。当然,您可以使用
try/catch
块并在事后处理错误,但我会使用
x&&x.y&&x.y.z&&x.y.z
解决方案

(你不需要
==true
,除非你真的希望条件只有当
a
严格等于
true
时才为true,而不是当它是
1
“hi”
时才为true,但从你的问题来看,我想你已经知道了。)


你说过你不想为此使用函数,我也不觉得有必要使用函数,只是为了适应和咯咯笑:

function ref(obj, names) {
    var rv = obj, index;
    if (names) {
        for (index = 0; rv && index < names.length; ++index) {
            rv = rv[names[index]];
        }
    }
    return rv;
}
函数调用是

或者:

function ref(obj) {
    var rv = obj, index;
    for (index = 1; rv && index < arguments.length; ++index) {
        rv = rv[arguments[index]];
    }
    return rv;
}
…但是在大多数JavaScript引擎上,这会比较慢(
参数
往往比较慢)。但是再一次,你必须在一个循环中做上千次,速度才是一个问题

或者正如西姆所建议的,一个单一的变量(我避免了
分割,但并不昂贵):


|

这有效
:p

if ( $($($(x).prop('y')).prop('z')).prop('a') ) {
    // code
}
现场演示:


这是一个丑陋的模式,但至少它是一行,属性名称不必重复(不同于
x&&x.y&&x.y.z&&……
)。

最后一个是最短的。对于较长的名称,还可以使用:
var tmp=x;如果(tmp&&(tmp=tmp.verylongname)&&(tmp=tmp.evenlongernamebala)&&(tmp=tmp.doyougetit)){…}
。我想在这种情况下使用一个特殊的函数。@Jesse你能举个例子吗?@shershams:FWIW,我在我的答案中添加了几个。@T.J.Crowder+1。谢谢。是的,“a”变量只是一个例子。谢天谢地,我的方法是
val(x,'y.z.a')
(一个字符串)@ŠimeVidas:是的,我是在避免
拆分
,但这并不昂贵。添加(并修复了我今早醒来时想到的一个bug,如果这不是可悲的,我不知道是什么)。我喜欢它,尤其是当你有长的变量名时。唯一的缺点是-你必须小心使用括号。
if (ref(x, "y", "z", "a") === true) {
    // do something
}
function ref(obj, path) {
    var rv = obj, names = path.split("."), index;
    for (index = 0; rv && index < names.length; ++index) {
        rv = rv[names[index]];
    }
    return rv;
}
if (ref(x, "y.z.a") === true) {
    // do something
}
if ( $($($(x).prop('y')).prop('z')).prop('a') ) {
    // code
}