2013-03-14 104 views
2

我可能會收到一個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

回答

1

如果你想捕捉所有深層嵌套的對象上可能出現的錯誤,那麼您可以使用多個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測試,但他們在語言中使用,因爲他們非常善於幫助解決某些類型的問題。

2

假設你不能影響你正在使用的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

0

醜陋,討厭,可怕的方式是使用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,但不會檢查非枚舉屬性(例如,內置對象的本地方法)。

所以確實沒有通用的解決方案,您只能針對特定情況定製一個解決方案。