检查JavaScript中深层嵌套对象属性是否存在的最简单方法是什么?

Mor*_*eng 23 javascript properties

我必须检查深层嵌套的对象属性,例如YAHOO.Foo.Bar.xyz.

我目前使用的代码是

if (YAHOO && YAHOO.Foo && YAHOO.Foo.Bar && YAHOO.Foo.Bar.xyz) {
    // operate on YAHOO.Foo.Bar.xyz
}
Run Code Online (Sandbox Code Playgroud)

这有效,但看起来很笨拙.

有没有更好的方法来检查这种深层嵌套的属性?

jfr*_*d00 19

如果你希望YAHOO.Foo.Bar成为一个有效的对象,但是为了防止你的代码是防弹的,那么只要把一个try catch放在它周围并让一个错误处理程序捕获任何缺失的段就可以是最干净的.然后,您可以使用一个if条件而不是四个来检测终端属性是否存在,以及一个catch处理程序,以便在中间对象不存在时捕获事物:

try {
    if (YAHOO.Foo.Bar.xyz) {
        // operate on YAHOO.Foo.Bar.xyz
} catch(e) {
    // handle error here
}
Run Code Online (Sandbox Code Playgroud)

或者,根据您的代码如何工作,它甚至可能只是这样:

try {
    // operate on YAHOO.Foo.Bar.xyz
} catch(e) {
    // do whatever you want to do when YAHOO.Foo.Bar.xyz doesn't exist
}
Run Code Online (Sandbox Code Playgroud)

我特别在处理应该是特定格式的外来输入时使用这些,但是无效输入是我想要捕获和处理自己而不是仅仅让异常向上传播的可能性.

一般来说,一些javascript开发人员使用try/catch.我发现有时候我可以用更大的功能块周围的单个try/catch替换5-10 if语句检查输入,并使代码更简单,更可读.显然,如果这是合适的,取决于特定的代码,但它绝对值得考虑.

仅供参考,如果通常的操作是不使用try/catch抛出异常,它可能比一堆if语句快得多.


如果您不想使用异常处理程序,可以创建一个函数来为您测试任意路径:

function checkPath(base, path) {
    var current = base;
    var components = path.split(".");
    for (var i = 0; i < components.length; i++) {
        if ((typeof current !== "object") || (!current.hasOwnProperty(components[i]))) {
            return false;
        }
        current = current[components[i]];
    }
    return true;
}
Run Code Online (Sandbox Code Playgroud)

用法示例:

var a = {b: {c: {d: 5}}};
if (checkPath(a, "b.c.d")) {
    // a.b.c.d exists and can be safely accessed
}
Run Code Online (Sandbox Code Playgroud)

  • 不要滥用尝试捕获这样的.亲爱的上帝,我的眼睛.甚至是一个空的挡块.如果我见过这个,那就是代码味道. (11认同)
  • @Raynos - 为什么这会滥用try/catch?对我来说,比检查所有中间级别的多个嵌套if语句更有意义.空捕获只是意味着如果中间级别不存在(合理的设计选择),您故意不想做任何事情.这是完美的代码.您是否真的喜欢投票,因为您更喜欢不同的方法?使用像这样的try/catch绝对没有错. (7认同)
  • "异常的发生,特殊条件改变了程序执行的正常流程." 我发现声称不存在的属性是"改变程序执行正常流程的特殊条件"是一个巨大的延伸.我认为你使用错误的工具来完成工作. (2认同)
  • 通常不希望存在的中间属性很可能是“改变程序执行的正常流程的特殊条件”,并且似乎是异常的完美用法。您似乎认为异常仅应用于特殊情况,但它们只是另一种错误返回/传播机制,在许多情况下,尤其是在处理外部异常时,可以比多个if语句更有效地使用异常。您不必控制的输入,并且测试每个操作可能会非常昂贵。 (2认同)

Ker*_*mes 7

var _ = {};

var x = ((YAHOO.Foo || _).Bar || _).xyz;
Run Code Online (Sandbox Code Playgroud)

  • 竖起大拇指本周最不明确的一行. (6认同)

Šim*_*das 6

考虑这个效用函数:

function defined(ref, strNames) {
    var name;
    var arrNames = strNames.split('.');

    while (name = arrNames.shift()) {        
        if (!ref.hasOwnProperty(name)) return false;
        ref = ref[name];
    } 

    return true;
}
Run Code Online (Sandbox Code Playgroud)

用法:

if (defined(YAHOO, 'Foo.Bar.xyz')) {
    // operate on YAHOO.Foo.Bar.xyz
}
Run Code Online (Sandbox Code Playgroud)

现场演示: http ://jsfiddle.net/DWefK/5/