Javascript对象会导致脚本停止执行

问题描述:

我可能会收到一个JSON结构这样Javascript对象会导致脚本停止执行

foo: {} 

或者我可能会喜欢这样的:

foo: {bar: {baz: 1} } 

当我检查第一数据结构像这样的存在:

if (data.foo.bar.baz) { } 

脚本完全停止运行。我在浏览器或任何东西上看不到任何javascript错误。它只是停止。无论哪种方式,这将是很好能够做到以上,而不是:

if (data.foo && data.foo.bar && data.foo.bar.baz) { } 

什么是解决这个问题的最好方法?

+0

哎呀,我什至不能这样做? var baz = data.foo.bar.baz;如果foo未定义,那么在该行之后的脚本中没有任何反应。 – Stefan 2013-03-14 04:06:59

+1

这是怎么回事? – allenhwkim 2013-03-14 04:09:42

+0

可以请你发布所有'ajax()'代码吗? (假设它是'ajax()'...) – Jace 2013-03-14 04:11:02

如果你想捕捉所有深层嵌套的对象上可能出现的错误,那么您可以使用多个if条件:

if (data && data.foo && data.foo.bar && data.foo.bar.baz) { } 

或者,如果失败不是预期的情况下,你可以使用异常处理程序:

try { 
    var item = data.foo.bar.baz; 
    // operate on item 
} catch(e) { 
    // perform any actions when it failed 
} 

有时候用一个异常处理程序保护代码块可以极大地简化您的错误处理。当异常触发时,例外情况会比if测试更差,因此您应该牢记这一点,但意外故障通常是异常处理的最佳选择,有时它们可​​能会真正简化代码的其余部分。

似乎有些开发人员基本上从不想用异常进行编码,宁愿使用大量的if测试,但他们在语言中使用,因为他们非常善于帮助解决某些类型的问题。

假设你不能影响你正在使用的JSON,你正在检查的方式几乎是这样做的唯一方法。虽然我更喜欢检查!== undefined。这纯粹是我的编程特质,因为我不喜欢考虑if (object)检查object的有效性。我总是将该行等同于if(object === true),这从布尔逻辑的角度来看并不是一回事。

if (data.foo !== undefined && data.foo.bar !== undefined && data.foo.bar.baz !== undefined) { } 

您也许能不检查data.foo !== undefined就完事了,既然你说FOO可能是一个空的对象。

如果你的代码将有很多这些检查,你可以做一个检查收到的JSON数据时,前面并填写缺少的对象:

if (data.foo === undefined) data.foo = {}; 
if (data.foo.bar === undefined) data.foo.bar = {}; 
if (data.foo.bar.baz === undefined) data.foo.bar.baz = null; // or skip this, I suppose... 
+0

谢谢,Scott!我喜欢定义我期望定义的内容,但碰巧不是。 – Stefan 2013-03-14 05:06:41

丑陋,讨厌,可怕的方式是使用evaltry..catch。一个更可靠的方法是使用typeof

if (typeof foo != 'undefined' && foo !== Null && 
    typeof foo.bar != 'undefined' && foo.bar !== Null && 
    ... 
) { 
    // stuff 
} 

但是,如果最后一个属性具有比其他undefined一个值,该值仅适用(即它将在​​财产存在,但未定义值失败)。

您可以创建一个更准确的通用性能测试仪来测试自己的属性:

function testChain(obj) { 

    for (var i=1, iLen=arguments.length; i<iLen; i++) { 

     if (obj.hasOwnProperty(arguments[i])) { 
      obj = obj[arguments[i]]; 

     } else { 
      return false; 
     } 
    } 
    return true; 
} 

alert(testChain({a:{b:'b'}}, 'a', 'b')); // true 

但不会检查继承属性。要检查这些内容,可以使用propertyIsEnumerable,但不会检查非枚举属性(例如,内置对象的本地方法)。

所以确实没有通用的解决方案,您只能针对特定情况定制一个解决方案。