<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                # 錯誤處理機制 ## Error 實例對象 JavaScript 解析或運行時,一旦發生錯誤,引擎就會拋出一個錯誤對象。JavaScript 原生提供`Error`構造函數,所有拋出的錯誤都是這個構造函數的實例。 ```javascript var err = new Error('出錯了'); err.message // "出錯了" ``` 上面代碼中,我們調用`Error`構造函數,生成一個實例對象`err`。`Error`構造函數接受一個參數,表示錯誤提示,可以從實例的`message`屬性讀到這個參數。拋出`Error`實例對象以后,整個程序就中斷在發生錯誤的地方,不再往下執行。 JavaScript 語言標準只提到,`Error`實例對象必須有`message`屬性,表示出錯時的提示信息,沒有提到其他屬性。大多數 JavaScript 引擎,對`Error`實例還提供`name`和`stack`屬性,分別表示錯誤的名稱和錯誤的堆棧,但它們是非標準的,不是每種實現都有。 - **message**:錯誤提示信息 - **name**:錯誤名稱(非標準屬性) - **stack**:錯誤的堆棧(非標準屬性) 使用`name`和`message`這兩個屬性,可以對發生什么錯誤有一個大概的了解。 ```javascript if (error.name) { console.log(error.name + ': ' + error.message); } ``` `stack`屬性用來查看錯誤發生時的堆棧。 ```javascript function throwit() { throw new Error(''); } function catchit() { try { throwit(); } catch(e) { console.log(e.stack); // print stack trace } } catchit() // Error // at throwit (~/examples/throwcatch.js:9:11) // at catchit (~/examples/throwcatch.js:3:9) // at repl:1:5 ``` 上面代碼中,錯誤堆棧的最內層是`throwit`函數,然后是`catchit`函數,最后是函數的運行環境。 ## 原生錯誤類型 `Error`實例對象是最一般的錯誤類型,在它的基礎上,JavaScript 還定義了其他6種錯誤對象。也就是說,存在`Error`的6個派生對象。 ### SyntaxError 對象 `SyntaxError`對象是解析代碼時發生的語法錯誤。 ```javascript // 變量名錯誤 var 1a; // Uncaught SyntaxError: Invalid or unexpected token // 缺少括號 console.log 'hello'); // Uncaught SyntaxError: Unexpected string ``` 上面代碼的錯誤,都是在語法解析階段就可以發現,所以會拋出`SyntaxError`。第一個錯誤提示是“token 非法”,第二個錯誤提示是“字符串不符合要求”。 ### ReferenceError 對象 `ReferenceError`對象是引用一個不存在的變量時發生的錯誤。 ```javascript // 使用一個不存在的變量 unknownVariable // Uncaught ReferenceError: unknownVariable is not defined ``` 另一種觸發場景是,將一個值分配給無法分配的對象,比如對函數的運行結果賦值。 ```javascript // 等號左側不是變量 console.log() = 1 // Uncaught ReferenceError: Invalid left-hand side in assignment ``` 上面代碼對函數`console.log`的運行結果賦值,結果引發了`ReferenceError`錯誤。 ### RangeError 對象 `RangeError`對象是一個值超出有效范圍時發生的錯誤。主要有幾種情況,一是數組長度為負數,二是`Number`對象的方法參數超出范圍,以及函數堆棧超過最大值。 ```javascript // 數組長度不得為負數 new Array(-1) // Uncaught RangeError: Invalid array length ``` ### TypeError 對象 `TypeError`對象是變量或參數不是預期類型時發生的錯誤。比如,對字符串、布爾值、數值等原始類型的值使用`new`命令,就會拋出這種錯誤,因為`new`命令的參數應該是一個構造函數。 ```javascript new 123 // Uncaught TypeError: number is not a func var obj = {}; obj.unknownMethod() // Uncaught TypeError: obj.unknownMethod is not a function ``` 上面代碼的第二種情況,調用對象不存在的方法,也會拋出`TypeError`錯誤,因為`obj.unknownMethod`的值是`undefined`,而不是一個函數。 ### URIError 對象 `URIError`對象是 URI 相關函數的參數不正確時拋出的錯誤,主要涉及`encodeURI()`、`decodeURI()`、`encodeURIComponent()`、`decodeURIComponent()`、`escape()`和`unescape()`這六個函數。 ```javascript decodeURI('%2') // URIError: URI malformed ``` ### EvalError 對象 `eval`函數沒有被正確執行時,會拋出`EvalError`錯誤。該錯誤類型已經不再使用了,只是為了保證與以前代碼兼容,才繼續保留。 ### 總結 以上這6種派生錯誤,連同原始的`Error`對象,都是構造函數。開發者可以使用它們,手動生成錯誤對象的實例。這些構造函數都接受一個參數,代表錯誤提示信息(message)。 ```javascript var err1 = new Error('出錯了!'); var err2 = new RangeError('出錯了,變量超出有效范圍!'); var err3 = new TypeError('出錯了,變量類型無效!'); err1.message // "出錯了!" err2.message // "出錯了,變量超出有效范圍!" err3.message // "出錯了,變量類型無效!" ``` ## 自定義錯誤 除了 JavaScript 原生提供的七種錯誤對象,還可以定義自己的錯誤對象。 ```javascript function UserError(message) { this.message = message || '默認信息'; this.name = 'UserError'; } UserError.prototype = new Error(); UserError.prototype.constructor = UserError; ``` 上面代碼自定義一個錯誤對象`UserError`,讓它繼承`Error`對象。然后,就可以生成這種自定義類型的錯誤了。 ```javascript new UserError('這是自定義的錯誤!'); ``` ## throw 語句 `throw`語句的作用是手動中斷程序執行,拋出一個錯誤。 ```javascript if (x <= 0) { throw new Error('x 必須為正數'); } // Uncaught ReferenceError: x is not defined ``` 上面代碼中,如果變量`x`小于等于`0`,就手動拋出一個錯誤,告訴用戶`x`的值不正確,整個程序就會在這里中斷執行。可以看到,`throw`拋出的錯誤就是它的參數,這里是一個`Error`實例。 `throw`也可以拋出自定義錯誤。 ```javascript function UserError(message) { this.message = message || '默認信息'; this.name = 'UserError'; } throw new UserError('出錯了!'); // Uncaught UserError {message: "出錯了!", name: "UserError"} ``` 上面代碼中,`throw`拋出的是一個`UserError`實例。 實際上,`throw`可以拋出任何類型的值。也就是說,它的參數可以是任何值。 ```javascript // 拋出一個字符串 throw 'Error!'; // Uncaught Error! // 拋出一個數值 throw 42; // Uncaught 42 // 拋出一個布爾值 throw true; // Uncaught true // 拋出一個對象 throw { toString: function () { return 'Error!'; } }; // Uncaught {toString: ?} ``` 對于 JavaScript 引擎來說,遇到`throw`語句,程序就中止了。引擎會接收到`throw`拋出的信息,可能是一個錯誤實例,也可能是其他類型的值。 ## try...catch 結構 一旦發生錯誤,程序就中止執行了。JavaScript 提供了`try...catch`結構,允許對錯誤進行處理,選擇是否往下執行。 ```javascript try { throw new Error('出錯了!'); } catch (e) { console.log(e.name + ": " + e.message); console.log(e.stack); } // Error: 出錯了! // at <anonymous>:3:9 // ... ``` 上面代碼中,`try`代碼塊拋出錯誤(上例用的是`throw`語句),JavaScript 引擎就立即把代碼的執行,轉到`catch`代碼塊,或者說錯誤被`catch`代碼塊捕獲了。`catch`接受一個參數,表示`try`代碼塊拋出的值。 如果你不確定某些代碼是否會報錯,就可以把它們放在`try...catch`代碼塊之中,便于進一步對錯誤進行處理。 ```javascript try { f(); } catch(e) { // 處理錯誤 } ``` 上面代碼中,如果函數`f`執行報錯,就會進行`catch`代碼塊,接著對錯誤進行處理。 `catch`代碼塊捕獲錯誤之后,程序不會中斷,會按照正常流程繼續執行下去。 ```javascript try { throw "出錯了"; } catch (e) { console.log(111); } console.log(222); // 111 // 222 ``` 上面代碼中,`try`代碼塊拋出的錯誤,被`catch`代碼塊捕獲后,程序會繼續向下執行。 `catch`代碼塊之中,還可以再拋出錯誤,甚至使用嵌套的`try...catch`結構。 ```javascript var n = 100; try { throw n; } catch (e) { if (e <= 50) { // ... } else { throw e; } } // Uncaught 100 ``` 上面代碼中,`catch`代碼之中又拋出了一個錯誤。 為了捕捉不同類型的錯誤,`catch`代碼塊之中可以加入判斷語句。 ```javascript try { foo.bar(); } catch (e) { if (e instanceof EvalError) { console.log(e.name + ": " + e.message); } else if (e instanceof RangeError) { console.log(e.name + ": " + e.message); } // ... } ``` 上面代碼中,`catch`捕獲錯誤之后,會判斷錯誤類型(`EvalError`還是`RangeError`),進行不同的處理。 ## finally 代碼塊 `try...catch`結構允許在最后添加一個`finally`代碼塊,表示不管是否出現錯誤,都必需在最后運行的語句。 ```javascript function cleansUp() { try { throw new Error('出錯了……'); console.log('此行不會執行'); } finally { console.log('完成清理工作'); } } cleansUp() // 完成清理工作 // Uncaught Error: 出錯了…… // at cleansUp (<anonymous>:3:11) // at <anonymous>:10:1 ``` 上面代碼中,由于沒有`catch`語句塊,一旦發生錯誤,代碼就會中斷執行。中斷執行之前,會先執行`finally`代碼塊,然后再向用戶提示報錯信息。 ```javascript function idle(x) { try { console.log(x); return 'result'; } finally { console.log('FINALLY'); } } idle('hello') // hello // FINALLY ``` 上面代碼中,`try`代碼塊沒有發生錯誤,而且里面還包括`return`語句,但是`finally`代碼塊依然會執行。而且,這個函數的返回值還是`result`。 下面的例子說明,`return`語句的執行是排在`finally`代碼之前,只是等`finally`代碼執行完畢后才返回。 ```javascript var count = 0; function countUp() { try { return count; } finally { count++; } } countUp() // 0 count // 1 ``` 上面代碼說明,`return`語句里面的`count`的值,是在`finally`代碼塊運行之前就獲取了。 下面是`finally`代碼塊用法的典型場景。 ```javascript openFile(); try { writeFile(Data); } catch(e) { handleError(e); } finally { closeFile(); } ``` 上面代碼首先打開一個文件,然后在`try`代碼塊中寫入文件,如果沒有發生錯誤,則運行`finally`代碼塊關閉文件;一旦發生錯誤,則先使用`catch`代碼塊處理錯誤,再使用`finally`代碼塊關閉文件。 下面的例子充分反映了`try...catch...finally`這三者之間的執行順序。 ```javascript function f() { try { console.log(0); throw 'bug'; } catch(e) { console.log(1); return true; // 這句原本會延遲到 finally 代碼塊結束再執行 console.log(2); // 不會運行 } finally { console.log(3); return false; // 這句會覆蓋掉前面那句 return console.log(4); // 不會運行 } console.log(5); // 不會運行 } var result = f(); // 0 // 1 // 3 result // false ``` 上面代碼中,`catch`代碼塊結束執行之前,會先執行`finally`代碼塊。 `catch`代碼塊之中,觸發轉入`finally`代碼塊的標志,不僅有`return`語句,還有`throw`語句。 ```javascript function f() { try { throw '出錯了!'; } catch(e) { console.log('捕捉到內部錯誤'); throw e; // 這句原本會等到finally結束再執行 } finally { return false; // 直接返回 } } try { f(); } catch(e) { // 此處不會執行 console.log('caught outer "bogus"'); } // 捕捉到內部錯誤 ``` 上面代碼中,進入`catch`代碼塊之后,一遇到`throw`語句,就會去執行`finally`代碼塊,其中有`return false`語句,因此就直接返回了,不再會回去執行`catch`代碼塊剩下的部分了。 `try`代碼塊內部,還可以再使用`try`代碼塊。 ```javascript try { try { consle.log('Hello world!'); // 報錯 } finally { console.log('Finally'); } console.log('Will I run?'); } catch(error) { console.error(error.message); } // Finally // consle is not defined ``` 上面代碼中,`try`里面還有一個`try`。內層的`try`報錯(`console`拼錯了),這時會執行內層的`finally`代碼塊,然后拋出錯誤,被外層的`catch`捕獲。 ## 參考連接 - Jani Hartikainen, [JavaScript Errors and How to Fix Them](http://davidwalsh.name/fix-javascript-errors)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看