(72)Wangdao.com第十二天_JavaScript 錯誤處理機制

1. Error 實例對象數組

JavaScript 解析或運行時,一旦發生錯誤,引擎就會拋出一個錯誤對象。函數

JavaScript 原生提供Error構造函數,全部拋出的錯誤都是這個構造函數的實例。this

  • var err = new Error('出錯了');
    err.message    // "出錯了"

    拋出Error實例對象之後,整個程序就中斷在發生錯誤的地方,再也不往下執行spa

 

  • 屬性
    • .message    錯誤提示信息
    • .name    錯誤名稱 ( 非標準屬性 )
    • .stack    錯誤的堆棧 ( 非標準屬性 )
      • 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
        // 錯誤堆棧的最內層是 函數
        // 而後是 函數
        // 最後是函數的運行環境
        throwitcatchit

         

    • 大多數 JavaScript 引擎,對Error實例還提供namestack屬性,分別表示錯誤的名稱錯誤的堆棧,但它們是非標準的,不是每種實現都有

 

2. 原生錯誤類型prototype

Error實例對象是最通常的錯誤類型,code

在 Error 的基礎上,JavaScript 還定義了 Error 的 6 個派生對象對象

  • // 開發者可使用它們,手動生成錯誤對象的實例
    var err1 = new Error('出錯了!');
    var err2 = new RangeError('出錯了,變量超出有效範圍!');
    var err3 = new TypeError('出錯了,變量類型無效!');
    
    err1.message // "出錯了!"
    err2.message // "出錯了,變量超出有效範圍!"
    err3.message // "出錯了,變量類型無效!"

     


  • SyntaxError 對象 是解析代碼時發生的語法錯誤
    • // 變量名錯誤
      var 1a;    // Uncaught SyntaxError: Invalid or unexpected token
      
      // 缺乏括號
      console.log 'hello');    // Uncaught SyntaxError: Unexpected string
      
      // 上面代碼的錯誤,都是在語法解析階段就能夠發現,因此會拋出 SyntaxError // 第一個錯誤提示是「token 非法」, // 第二個錯誤提示是「字符串不符合要求」

       

  • ReferenceError 對象 是引用一個不存在的變量時發生的錯誤
    • 使用一個不存在的變量
    • 將一個值賦予沒法分配的對象

 

  • RangeError 對象 是一個值超出有效範圍時發生的錯誤。
    • 數組長度爲負數
    • Number對象的方法參數超出範圍
    • 函數堆棧超過最大值

 

  • TypeError 對象 是變量或參數不是預期類型時發生的錯誤
    • 對字符串、布爾值、數值等原始類型的值使用new命令, 就會拋出這種錯誤,由於new命令的參數應該是一個構造函數
    • 調用對象不存在的方法,也會拋出TypeError錯誤

 

  • URIError 對象 是 URI 相關函數的參數不正確時拋出的錯誤
    • 主要涉及encodeURI()decodeURI()encodeURIComponent()decodeURIComponent()escape()unescape()這六個函數

 

  • EvalError 對象 是 eval函數 沒有被正確執行時,會拋出 EvalError
    • 該錯誤類型已經再也不使用了,只是爲了保證與之前代碼兼容,才繼續保留

 

3. 自定義錯誤blog

除了 JavaScript 原生提供的七種錯誤對象,還能夠定義本身的錯誤對象繼承

  • function UserError(message) {
        this.message = message || '默認信息';
        this.name = 'UserError';
    }
    
    UserError.prototype = new Error();
    UserError.prototype.constructor = UserError;

    // 上面代碼自定義一個錯誤對象,讓它繼承對象。而後,就能夠生成這種自定義類型的錯誤了
    UserErrorErrorvar mineErr = new UserError('這是自定義的錯誤!');

    // throw也能夠拋出自定義錯誤
    throwthrow new UserError('出錯了!');

     

4. throw 中斷程序,拋出錯誤token

throw語句的做用是手動中斷程序執行,拋出一個錯誤

  • if (x <= 0) {
      throw new Error('x 必須爲正數');
    }
    // Uncaught ReferenceError: x is not defined

     

  • throw 能夠拋出任何類型的值。也就是說,它的參數能夠是任何值
  • 引擎會接收到throw拋出的信息,多是一個錯誤實例,也多是其餘類型的值

 

5. try...catch

JavaScript 提供了try...catch結構,容許對錯誤進行處理,選擇是否往下執行

  • try代碼塊拋出錯誤(上例用的是throw語句),JavaScript 引擎就當即把代碼的執行,轉到catch代碼塊,或者說錯誤被catch代碼塊捕獲了。catch接受一個參數,表示try代碼塊拋出的值
    • try {
        throw new Error('出錯了!');
      } catch (e) {
        console.log(e.name + ": " + e.message);
        console.log(e.stack);
      }
      // Error: 出錯了!
      //   at <anonymous>:3:9
      //   ...

       

  • catch代碼塊捕獲錯誤以後,程序不會中斷,會按照正常流程繼續執行下去
    • try {
          throw "出錯了";
      } catch (e) {
          console.log(111);
      }
      console.log(222);
      // 111
      // 222

       

  • catch代碼塊之中,還能夠再拋出錯誤,甚至使用嵌套的try...catch結構
    • var n = 100;
      
      try {
            throw n;
      } catch (e) {
          if (e <= 50) {
              // ...
          } else {
              throw e;
          }
      }
      // Uncaught 100

       

  • 爲了捕捉不一樣類型的錯誤,catch代碼塊之中能夠加入判斷語句
    • 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);
          }
          // ...
      }EvalErrorRangeError

       

6. finnally 代碼塊

try...catch結構容許在最後添加一個finally代碼塊,表示無論是否出現錯誤,都必需在最後運行的語句

  • function cleansUp() {
        try {
            throw new Error('出錯了……');
            console.log('此行不會執行');
        } finally {
            console.log('完成清理工做');
        }
    }
    
    cleansUp()
    // 完成清理工做
    // Error: 出錯了……

     

  • finally代碼塊用法的典型場景
    • openFile();
      
      try {
          writeFile(Data);
      } catch(e) {
          handleError(e);
      } finally {
          closeFile();
      }

      首先打開一個文件,而後在try代碼塊中寫入文件,若是沒有發生錯誤,則運行finally代碼塊關閉文件;一旦發生錯誤,則先使用catch代碼塊處理錯誤,再使用finally代碼塊關閉文件

  • try...catch...finally這三者之間的執行順序
    • 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
相關文章
相關標籤/搜索