2016-08-16 89 views
2

我正在閱讀Eloquent JavaScript的第8章「Bugs and Error Handling」。我遇到了一個關於錯誤代碼的例子,但我仍然無法理解作者給出的導致失敗原因的所有解釋。讓我們給的背景:在節「Selective Catching」上撰文說:有人能澄清我這個try-catch塊(未定義變量)有什麼問題嗎? (選擇性捕捉,JS)

Invalid uses of the language, such as referencing a nonexistent variable, looking up a property on null, or calling something that’s not a function, will also result in exceptions being raised. Such exceptions can be caught just like your own exceptions.

When a catch body is entered, all we know is that something in our try body caused an exception. But we don’t know what, or which exception it caused.

JavaScript (in a rather glaring omission) doesn’t provide direct support for selectively catching exceptions: either you catch them all or you don’t catch any. This makes it very easy to assume that the exception you get is the one you were thinking about when you wrote the catch block.

But it might not be. Some other assumption might be violated, or you might have introduced a bug somewhere that is causing an exception. Here is an example, which attempts to keep on calling promptDirection until it gets a valid answer:

for (;;) { 
    try { 
    var dir = promtDirection("Where?"); // ← typo! 
    console.log("You chose ", dir); 
    break; 
    } catch (e) { 
    console.log("Not a valid direction. Try again."); 
    } 
} 

The for (;;) construct is a way to intentionally create a loop that doesn’t terminate on its own. We break out of the loop only when a valid direction is given. But we misspelled promptDirection, which will result in an 「undefined variable」 error. Because the catch block completely ignores its exception value (e), assuming it knows what the problem is, it wrongly treats the variable error as indicating bad input. Not only does this cause an infinite loop, but it also 「buries」 the useful error message about the misspelled variable.

我想我沒有得到解釋,因爲Enlgish是不是我的母語。我沒有得到的是大膽的句子。我不明白爲什麼catch塊會忽略變量e以及關於錯誤輸入的信息。 catch catch是否認爲e是一個糟糕的輸入?

請問有人可以澄清一下。提前致謝。

+0

我*認爲*解釋假設函數'promptDirection()'將顯式地拋出異常,如果輸入的輸入無效。因此,從'try'塊引發的異常可能是輸入無效,或者來自意想不到的事情 - 比如函數名稱中的拼寫錯誤。 'catch'塊不檢查異常('e'),所以它的行爲就好像用戶輸入了錯誤的東西,即使用戶實際上沒有機會輸入。 – Pointy

+0

感謝隊友,現在好多了! –

回答

2

作者正試圖做的一點是,它是如何設置錯誤處理的。讓我們假設在你的程序中建立錯誤處理的目標之一是讓它更容易捕捉和解決錯誤出現時的問題。

那麼如果是這樣的話,那麼作者在這裏說明的是這是一個錯誤處理的例子,它隱藏了真正的問題,使得bug實際上更難。

它是如何隱藏問題的?那麼,如果你看看那裏的代碼,它很好地設置了一個try塊。但是,在catch聲明中,它並不打算檢查是否發現了哪種錯誤。它只是假設拋出的錯誤總是與無效的方向有關。

但事實並非如此!因爲正如作者告訴你的那樣,函數名實際上拼錯了,這會觸發一個「未定義的變量」錯誤。但是,由於catch塊不會檢查錯誤e的屬性,用戶將永遠不會知道這是發生的錯誤。相反,他們總是會看到「不是有效的方向,請重試。」但是,如果存在「未定義的變量」錯誤,那實際上是錯誤的。問題源於不正確的用戶輸入,而不是代碼本身!這個例子特別糟糕,實際上,因爲編碼器的錯誤看起來像是用戶錯誤。

那麼我們如何以正確的方式做到這一點?那麼,有很多方法。最簡單的事情將是使輸出到控制檯指示已經扔了,像這樣的錯誤:

for (;;) { 
    try { 
    var dir = promtDirection("Where?"); // ← typo! 
    console.log("You chose ", dir); 
    break; 
    } catch (e) { 
    console.log(e.name, ': ', e.msg); 
    } 
} 

更重要的是,讓我們說,我們promptDirection功能可以拋出一個自定義錯誤,看起來像這樣:

function InvalidDirectionError(message) { 
    this.name = 'InvalidDirectionError'; 
    this.message = message || 'Not a valid direction. Try again.'; 
    this.stack = (new Error()).stack; 
} 
InvalidDirectionError.prototype = Object.create(Error.prototype); 
InvalidDirectionError.prototype.constructor = InvalidDirectionError; 

然後在我們的catch語句中,我們可以這樣做:

for (;;) { 
    try { 
    var dir = promtDirection("Where?"); // ← typo! 
    console.log("You chose ", dir); 
    break; 
    } catch (e) { 
    if (e.name == 'InvalidDirectionError') { 
     console.log(e.msg); 
    } else { 
     console.log(e.name, ': ', e.msg); 
    } 
    } 
} 

我希望這有助於。請評論,如果你需要進一步澄清。

+0

非常感謝您的回答。這很清楚,是我喜歡閱讀的那種答案。感謝您花時間回答我。 –

3

這裏的假設是,promptDirection有時會在其輸入無效時引發錯誤,作爲其正常操作的一部分。這段代碼應該能夠捕獲無效輸入中引發的錯誤。想象一下,像這樣:

function promptDirection(text) { 
    var value = prompt(text); 
    if(value != "up" && value != "down") { 
     throw new Error("not a valid direction"); 
    } 
    return value; 
} 

然而,promptDirection這裏被誤拼爲promtDirection

But we misspelled promptDirection, which will result in an 「undefined variable」 error.

因此,代碼將總是引發錯誤,這不是假想作者的意圖(即,只有在無效輸入時纔會產生錯誤)。

你可以使用e來測試預期的錯誤類型:

catch(e) { 
    if(e.message == "not a valid direction") { 
     console.log("Not a valid direction. Try again."); 
    } else { 
     console.log("Something else went wrong:" + e.message); 
    } 
} 
+0

謝謝,你的解釋幫助我理解它!而且,現在我明白了更好的try-catch塊! –

3

作者是不是說的JavaScript總是忽略e;他正在談論這個具體的例子。這個例子的代碼寫的不好(故意):

catch (e) { 
    console.log("Not a valid direction. Try again."); 
} 

我們捕捉異常(稱爲e),但我們千萬不要揣摩例外的是什麼。我們只是總是,總是說「不是一個有效的方向,再試一次。」

此代碼假設只有一件事可能出錯:輸入無效。

+0

你在回答,其他同學的回答給了這個觀點正確的理解。感謝您的回答並幫助我! –

相關問題