亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JavaScript錯誤處理操作實例詳解

發布時間:2020-08-31 09:49:01 來源:腳本之家 閱讀:149 作者:deniro_li 欄目:web開發

本文實例講述了JavaScript錯誤處理操作。分享給大家供大家參考,具體如下:

良好的錯誤處理機制可以讓用戶得到及時的提醒,所以讓我們來看看 JavaScript 提供了哪些針對錯誤處理的工具和方法吧O(∩_∩)O~

1 try-catch 語句

ECMA-262 第 3 版引入了 try-catch 語句,這時 JavaScript 處理異常的標準方式:

try{
  //可能會導致錯誤的代碼
} catch (error){
  //錯誤處理
}

如果 try 塊中的代碼發生了錯誤,會立即執行 catch 塊的代碼。 catch 塊有一個包含錯誤信息的對象,它有一個 message 屬性,表示的是瀏覽器給出的錯誤消息:

<script type="text/javascript">
  try {
    window.someNonexistenceFunction();
  } catch (error) {
    console.log(error.message);
  }
</script>

message 屬性是所有的瀏覽器都支持的屬性,所以在跨瀏覽器編程中,最好只使用這個屬性。

1.1 finally 子句

finally 子句是可選的,如果使用了 finally 子句,里面包含的代碼是絕對會被執行的!甚至連 return 語句都無法阻止它被執行:

<script type="text/javascript">
  function testFinally() {
    try {
      return 2;
    } catch (error) {
      return 1;
    } finally {
      return 0;
    }
  }
  console.log(testFinally());//0
</script>

IE7 及更早的版本有一個 bug:除非有 catch 子句,否則 finally 中的代碼永遠不會被執行!IE8 修復了這個 bug。

注意:只要在代碼中使用了 finally 子句,那么不管 return 放在 try 還是 catch 語句中,都會被忽略!

1.2 錯誤類型

當錯誤發生時,會拋出相應類型的錯誤對象。ECMA-262 定義了 7 種錯誤類型:

  • Error
  • EvalError
  • RangeError
  • ReferenceError
  • SyntaxError
  • TypeError
  • URIError

1.2.1 Error

Error 是基類型,即其他的錯誤類型都是從 Error 繼承來的。可以利用 Error 來自定義錯誤類型。

1.2.2 EvalError

EvalError 是在使用 eval() 函數發生異常時被拋出。怎么才算是異常呢?如果沒有把 eval() 當作函數來使用,就會拋出 EvalError:

new eval();//拋出 EvalError
eval = foo;//拋出 EvalError

實際開發中很少這樣使用 eval() 函數的(除非腦袋秀逗了O(∩_∩)O~),所以很少會遇到 EvalError。

1.2.3 RangeError

RangeError 會在數值超出規定范圍時被拋出。比如在定義數組時,指定了數組不支持的數組項數,就會拋出這個錯誤:

var item1 = new Array(-20);//拋出 RangeError
var item1 = new Array(Number.MAX_VALUE);//拋出 RangeError

1.2.4 ReferenceError

找不到對象時,會拋出 ReferenceError(這就是瀏覽器的知名的 “object expected” 錯誤)。一般在訪問不存在的變量時,會拋出這個錯誤:

var obj = x;//x 還未被聲明,所以拋出 ReferenceError

1.2.5 SyntaxError

如果把帶著錯誤語法的字符串傳入 eval() 函數時,就會拋出 SyntaxError:

eval("a ++ b");//拋出 SyntaxError

eval() 函數之外的語法錯誤,會導致 JavaScript 立即停止執行,所以不會拋出這個錯誤!

1.2.6 TypeError

如果變量中保存著意外的類型,或者訪問不存在的方式時,就會拋出 TypeError。這個錯誤比較常見:

var o = new 10;//拋出 TypeError
alert("name" in true);//拋出 TypeError
Function.prototype.toString.call("name");//拋出 TypeError

如果傳遞給函數的參數類型與預期類型不符,也會拋出這個錯誤。

1.2.7 URIError

使用 encodeURI() 或者 decodeURI() 時,URI 的格式不正確,就會拋出 URIError 錯誤。一般很少發生,因為這兩個函數有著非常高的容錯性O(∩_∩)O~

可以針對這些錯誤類型進行恰當的處理:

try{
  someFunction();
} catch (error){
  if (error instanceof TypeError){
    //處理類型錯誤
  }
  ...
}

因為包含在 message 中的消息會因瀏覽器而異,所以在跨瀏覽器編程中,最好直接檢查這些錯誤類型。

1.3 合理使用 try-catch

try-catch 最適合用于那些我們無法控制的錯誤,比如使用了一個開源庫中的函數,而我們無法修改源代碼的情況。

而對于自定義的函數,驗證函數參數類型是否合法的情況,就不應該使用 try-catch,因為這個函數是我們可以修改的,在使用參數前先進行驗證才是正途。

2 拋出錯誤

throw 操作符可以拋出自定義的錯誤,必須要指定一個值,這個值可以是任意類型。代碼在遇到 throw 操作符時,會立即停止執行。只有在 try-catch 語句捕獲到被拋出的值時,才會繼續執行。

通過使用之前說過的內置錯誤類型,可以模擬瀏覽器錯誤。這些錯誤類型的構造函數都接收一個參數,即實際的錯誤消息:

throw new Error("Something bad happened.");

最常使用這些錯誤類型來創建自定義的錯誤消息:ErrorRangeErrorReferenceError TypeError

也可以利用原型鏈,通過繼承 Error 來創建自定義消息。比如,這里為新創建的錯誤類型指定了 name 和 message 屬性:

<script type="text/javascript">
  function CustomError(message) {
    this.name = "CustomError";
    this.message = message;
  }
  CustomError.prototype = new Error();
  throw new CustomError("My message");
</script>

這樣創建的自定義錯誤與瀏覽器錯誤并不同,所以可是很有用的哦O(∩_∩)O~

注意: IE 只有在拋出 Error 對象時才會顯示自定義的錯誤消息!其他錯誤對象,它只會顯示 “exception thrown and not caught”。

2.1 拋出錯誤的時機

應該在已知的、某種特定錯誤條件下(會導致函數無法正常執行),拋出自定義的錯誤:

<script type="text/javascript">
  function process(values) {
    if (!(values instanceof Array)) {
      throw new Error("process():Argument must be an array.");
    }
    values.sort();
    for (var i = 0, len = values.length; i < len; i++) {
      if (values[i] > 100) {
        return values[i];
      }
    }
    return -1;
  }
  process("hi");
</script>

如果給上面的函數傳入一個字符串參數,那么 sort() 就會拋錯,所以我們在這里加入了帶有適當消息的自定義錯誤。這對于一個有著幾千行腳本代碼的項目來說,可以顯著地提升代碼的可維護性O(∩_∩)O~

錯誤消息時包含了函數名稱以及為什么會發生錯誤的明確描述,是不是很清晰呀O(∩_∩)O~

在開發時,要注意函數可能失敗的因素,把這些因素都加上自定義錯誤吧!良好的錯誤處理機制是確保代碼只發生我們定義的錯誤。

2.2 拋出錯誤與使用 try-catch

建議在拋出錯誤時盡量提供詳盡的信息,因為我們拋出錯誤不就是為了在維護時,能夠知道錯誤發生的具體位置和具體原因的嗎?

3 錯誤事件

任何沒有通過 try-catch 處理的錯誤都會觸發 window 對象的 error 事件(IE、Firfox 和 chrome 支持)。它接收 3 個參數:錯誤消息、錯誤所在的 URL 和行號。一般只有錯誤消息有用。只能通過 DOM0 級技術來指定 onerror 事件處理程序,如果返回 false,就可以阻止瀏覽器報告錯誤的默認行為:

<script type="text/javascript">
  window.onerror= function (message,url,line) {
    console.log(message);
    return false;
  }
</script>

這個函數其實就是整個文檔的 try-catch 語句,它可以捕獲所有沒有被處理的運行時錯誤。理想情況下,錯誤都被包含在 try-catch 語句中,所以不會使用到它。

注意: 不同的瀏覽器下,這個函數的處理方式不同。在 IE 中,發生了 onerror 事件,代碼仍會執行,所有的變量和數據都會保留。但在 Firefox 中,代碼會停止執行,而且之前所有的變量和數據都會被銷毀!

圖像也支持 error 事件。如果圖像的 src 屬性中的 URL 無法返回被識別的圖像格式時,就會觸發持 error 事件。這時的 error 事件會返回一個以圖像為目標的 event 對象:

<script type="text/javascript">
  var image = new Image();
  EventUtil.addHandler(image, "load", function (event) {
    console.log("Image loaded!");
  });
  EventUtil.addHandler(image, "error", function (event) {
    console.log("Image not loaded!");
  });
  image.src = "smilex.gif";//實際并不存在
</script>

注意,如果發生了 error 事件,那么這個圖像的下載過程就已經結束咯。

4 常見的錯誤類型

因為 JavaScript 是松散類型的語言,所以錯誤只會在代碼運行期間發生。一般情況下,我們需要重點關注以下三種錯誤:

① 類型轉換錯誤
② 數據類型錯誤
③ 通信錯誤

4.1 類型轉換錯誤

在使用相等(==)或不相等(!==),或者在 if、for 或 while 中使用了非布爾值時,最常發生類型轉換錯誤。

所以建議使用全等(===)和不全等(!==)來避免類型轉換操作。

if 等語句會自動把任何值都轉換為布爾值:

function concat(str1, str2, str3){
  var result = str1 + str2;
  if (str3){//不要這樣!!!
    result +=str3;
  }
  return result;
}

這個函數是想拼接兩個或三個字符串,然后返回結果。所以這里的第三個參數是可選的,,所以必須要檢查。如果我們在調用這個函數時,只用到前兩個參數,這意味著第三個參數因為是未使用過的命名變量,所以被自動賦值給 undefine,而 undefine 在 if 中會被自動轉換為 false,這樣可以。但是,如果第三個參數傳入數值 0,在 if 中會被自動轉換為 false,那么就不會被加到 result 中!所以我們要進行檢查:

function concat(str1, str2, str3){
  var result = str1 + str2;
  if (typeof str3 == "string"){
    result +=str3;
  }
  return result;
}

4.2 數據類型錯誤

function getQueryString(url){
  var pos = url.indexOf("?");
  if (pos > -1){
    return url.substring(pos + 1);
  }
  return "";
}

這個函數打算返回給定 URL 中的查詢字符串。但如果傳入非字符串類型的參數,就會導致錯誤。所以要加上類型判斷:

function getQueryString(url){
  if(typeof url == "string"){
    var pos = url.indexOf("?");
    if (pos > -1){
      return url.substring(pos + 1);
    }
  }
  return "";
}

還有,如果在流控制語句中使用非布爾值也會導致數據類型錯誤:

function reverseSort(values){
  if (values){//非數組值都會報錯
    values.sort();
    values.reverse();
  }
}

另一種錯誤是將參數與 null 進行比較,這只能確保參數不是 null 和 undefined,也不建議將參數與 undefined 進行比較。

還有一種錯誤是,只針對某一特性進行檢測:

function reverseSort(values){
  if (typeof values.sort == "function"){
    values.sort();
    values.reverse();
  }
}

上面的函數,如果傳入帶有 sort() 方法的對象,就會通過檢測,但會在調用 reverse() 方法時報錯!所以這里最好是使用 instanceof 來檢測:

function reverseSort(values){
  if (values instanceof Array){
    values.sort();
    values.reverse();
  }
}

總的來說,基本類型的值使用 typeof 檢測,而對象的值使用 instanceof 來檢測。特別是面向公眾的 API,一定要執行類型檢查,以確保函數始終能夠正常執行。

4.3 通信錯誤

JavaScript 與服務器之間的任何一次通信,就有可能會產生錯誤。

一種通信錯誤是發送了不正確的 URL 格式數據。一般是沒有使用 encodeURIComponent() 對數據進行編碼,可以使用這里的函數來處理查詢字符串:

/**
 * 添加查詢字符串
 * @param url URL
 * @param name 參數名
 * @param value 參數值
 * @returns {*}
 */
function addQueryStringArg(url, name, value) {
  if (url.indexOf("?") == -1) {
    url += "?";
  } else {
    url += "&";
  }
  url += encodeURIComponent(name) + "=" + encodeURIComponent(value);
  return url;
}

盡量使用這個函數,就可以確保編碼正確。

5 區分致命錯誤與非致命錯誤

非致命錯誤可以根據以下列出的一個或多個條件來確定:

  • 不影響用戶的主要任務;
  • 只影響頁面的一部分;
  • 可以恢復;
  • 重復操作可以消除錯誤。

而致命錯誤也可以根據以下列出的一個或多個條件來確定:

  • 無法繼續執行;
  • 影響到了用戶的主要操作;
  • 導致其他連帶的錯誤。

如果發生了致命錯誤,要立即發送消息通知用戶,告訴他們無法再繼續操作咯。如果必須刷新頁面才會恢復,也必須通知用戶,并提供了可刷新頁面的按鈕。

比如,在大型網站中,可能有多個互不依賴的模塊,它們是類似這樣初始化的:

for (var i=0, len=mods.length; i<len; i++){
  mods[i].init();
}

這樣做的問題是,如果有一個模塊發生錯誤,那么就會導致后續的其它模塊無法被初始化,從而導致致命的錯誤!我們這樣改造下,讓致命的錯誤變成非致命的錯誤:

for (var i=0, len=mods.length; i<len; i++){
  try{
    mods[i].init();
  } catch (ex){
    ...
  }
}

6 把錯誤記錄到服務器

建議集中保存錯誤日志,這樣可以方便后續查找錯誤的原因。所以我們可以把 JavaScript 錯誤發送給服務器,讓服務器保存起來。這樣把前后端的錯誤集中起來管理,就可以很方便地對數據進行分析咯O(∩_∩)O~

首先先在服務器上創建一個接口,用于接收頁面發送的錯誤數據:

/**
 * 記錄 JavaScript 錯誤
 * @param sev 嚴重程度,比如:nonfatal
 * @param msg 錯誤消息
 */
function logError(sev,msg){
  var img=new Image();
  img.src="log.action?sev="+encodeURIComponent(sev)+"&msg="+encodeURIComponent(msg);
}

使用 Image 對象來發送請求,有這些好處:

  • 所有的瀏覽器都支持 Image 對象,包含那些不支持 XMLHttpRequest 對象的瀏覽器。
  • 可以避免跨域限制。比如可以使用一臺日志服務器專門接收多臺 web 服務器拋出的錯誤。

只要是使用了 try-catch 語句,就要把錯誤記錄到日志中:

for (var i=0, len=mods.length; i<len; i++){
  try{
    mods[i].init();
  } catch (ex){
    logError("nonfatal","模塊初始化失敗:"+ex.message);
  }
}

第二個參數是上下文信息以及 JavaScript 的錯誤消息,帶上上下文信息可以方便分析導致錯誤的真正原因。

更多關于JavaScript相關內容感興趣的讀者可查看本站專題:《JavaScript錯誤與調試技巧總結》、《JavaScript傳值操作技巧總結》、《javascript編碼操作技巧總結》、《JavaScript中json操作技巧總結》、《JavaScript切換特效與技巧總結》、《JavaScript查找算法技巧總結》、《JavaScript動畫特效與技巧匯總》、《JavaScript數據結構與算法技巧總結》、《JavaScript遍歷算法與技巧總結》及《JavaScript數學運算用法總結》

希望本文所述對大家JavaScript程序設計有所幫助。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

固安县| 神农架林区| 镇赉县| 体育| 兴隆县| 柏乡县| 霸州市| 蓝山县| 金华市| 湟中县| 鹤壁市| 马边| 登封市| 察雅县| 武邑县| 桂东县| 阜新| 尚志市| 双牌县| 毕节市| 泽普县| 刚察县| 昌都县| 临洮县| 高阳县| 佛教| 峨眉山市| 青河县| 高台县| 沙坪坝区| 德化县| 巴南区| 武夷山市| 福建省| 同心县| 五指山市| 光山县| 蒙城县| 北辰区| 英山县| 呼图壁县|