2011-05-26 65 views
5

我曾多次被告知,在javascript中使用異常是「壞」的。還沒有真正知道它爲什麼不好,但是我應該使用break,繼續並返回。在javascript中的例外,我應該使用它們以及如何?

這很好,除了我不需要返回/打破/繼續,我需要拋出。我有一種情況,我有迭代器函數互相嵌套,每個函數都會在調用時返回下一個值,所以我使用異常來表示沒有更多要迭代的東西:看起來像是一種合理的方式來執行代碼,使代碼清潔並在實踐中完美運作。真的有什麼理由不在js中使用例外嗎?

第二個問題,當我使用異常時,應該拋出什麼樣的對象?對於錯誤,我顯然會拋出Error的實例,但對於特殊情況(停止迭代等),我需要一個快速的方法來檢查這些特定的異常,我所做的只是定義一個空的命名函數(function StopIteration(){ }),因爲函數是通過引用來比較的,所以我總是可以檢查它是我的特例還是我應該重新拋出。在js中有更好或更具代表性的方法來做到這一點嗎?我應該真的嘗試重構我的代碼避免使用異常嗎?

謝謝

+0

我聽說'try {} catch(e){}閉包會顯着減慢執行速度。需要做測試來驗證。 – timdream 2011-05-26 14:49:28

+0

[Javascript Try-Catch Performance Vs的重複可能性。錯誤檢查代碼](http://stackoverflow.com/questions/3217294/javascript-try-catch-performance-vs-error-checking-code) – Pointy 2011-05-26 14:52:18

回答

2

異常處理通常比正常評估,只爲例外情況

停止迭代你是一個結束條件定義hasNext或IsEmpty函數的更好或返回較慢哨兵值(如undefined)時,有沒有更多的元素,以便循環將成爲

//with hasNext 
while(it.hasNext()){ 
var val = it.next(); 
//... 
} 
//or with a sentinal undefined 
while((val = it.next()) !== undefined){ 
//... 
} 
+0

謝謝!對於唯一名稱使用命名函數怎麼樣?這樣做是個好主意嗎? – fingerprint211b 2011-05-26 15:08:04

+0

你是什麼意思? (如果您接受我的回答,請點擊旁邊的ticmark來接受它)< – 2011-05-26 17:22:04

3

這聽起來像你正在尋找通過量h使用嵌套循環的多維空間,這是一個相當普遍的事情來編程。當發現目標被最外層循環周圍的「catch」塊捕獲時,從最內層循環中拋出一個異常很誘人,但這通常被認爲是不好的做法。

語言設計者意識到這個缺陷,所以他們允許我們給標籤(名稱)給循環結構,以便我們可以從它們中斷開(或繼續到它們)。考慮這個例子:

function findValueInMatrix(value, matrix) { 
    var r, c, coords, rows=matrix.length, cols=matrix[0].length; 
    found: // Label the outer loop as "found" so we can break from it. 
    for (r=0; r<rows; r++) { 
    for (c=0; c<cols; c++) { 
     if (matrix[r][c] == value) { 
     coords = [r, c] 
     break found; // Exit the loop labeled "found". 
     } 
    } 
    } 
    return coords; 
} 

你可以在this post about breaking from nested loops找到更多的信息。

這個jsPerf test case也表明,打破標籤名義上比拋出異常更快(大概在大多數瀏覽器中)。

+0

從'按異常編碼'維基百科頁面,您可以參考:'這種反模式與軟件異常處理無關' 。 – molnarg 2013-07-29 07:48:24

+0

@molnarg:是的,很好的觀察。我已刪除鏈接。 – maerics 2013-07-29 15:17:41

0

對於一些人來說,拋出異常來表明沒有更多的值是一種不好的風格;例外情況是例外行爲

此外,異常處理通常比簡單測試慢。 如果拋出的實例不是每次都創建,則區別是非常小的(也許甚至不存在)。所以有一個恆定的StopIteration並投擲它實際上是相當快的。

對於你的問題,你可能想看到https://developer.mozilla.org/en/JavaScript/Guide/Iterators_and_Generators(他們使用異常停止迭代)。 我發現在動態類型語言中,異常也用於這種目的。

-1

拋出異常打破嵌套遞歸搜索/步行的是要走的最簡單優雅方式。

說你走一棵樹,recursivelly調用一個函數處理當前節點,再次呼籲其每個孩子等等。

正如你過程的每個節點,你可能想completelly打破整個調用堆棧,並返回發現價值(或停止迭代一般),所有正在等待在前面的循環的突破調用。請注意,以前的這些調用在處理&內存時可能代價昂貴,但如果您「找到」了結果,則無用。拋出異常是實現這一點的最有效和最簡單的方式,但當然需要注意。

對於簡單的(甚至是嵌套的)循環而言,它是一種矯枉過正的行爲,並被正確地吹捧爲反模式。

+0

對於任何感興趣的人,可以使用JavaScript異常來使用異常http://jacob.jkrall.net/js-tco/來模仿tail-call優化裝飾器。 – 2015-11-19 14:58:37

+0

雖然性能很糟糕,但僅僅因爲你可以,並不意味着你應該。 – 2015-11-19 15:10:19

相關問題