【前言】

本文主要介绍下JS的Error name相关属性.
当 JS 引擎执行 JS代码时,会发生各种错误。

①语法错误,通常是程序员造成的编码错误或错别字;
②拼写错误或语言中缺少的功能(可能由于浏览器差异);
③来自服务器或用户的错误输出而导致的错误;
④由于许多其他不可预知的因素;

**当发生错误时,JS通常会停止并产生错误消息。技术术语是这样描述的:JavaScript 将抛出异常(抛出错误)。JS实际上会创建一个Error对象,该对象带有两个属性name和message。**

【概念】

 Error指程序中的非正常运行状态,在其他编程语言中称为“异常”或“错误”。解释器会为每个错误情形创建并抛出一个**Error对象,其中包含错误的描述信息。**

ECMAScript定义了六种类型的错误。除此之外,还可以使用Error构造方法创建自定义的error对象,并使用throw语句抛出该对象。
ReferenceError(参考错误):找不到对象/引用一个不存在的变量/函数时发生的错误。
在这里插入图片描述
TypeError(类型错误):错误的使用了类型或对象的方法时,变量或参数不是预期类型时发生的错误。比如,对字符串、布尔值、数值等原始类型的值使用new命令,就会抛出这种错误,因为new命令的参数应该是一个构造函数。
RangeError(范围错误):使用内置对象的方法时,参数超范围
SyntaxError(语法错误):解析代码时发生的语法错误,语法写错了。
EvalError(评估错误):错误的使用了Eval
URIError(url错误):URI错误。URIError对象是 URI 相关函数的参数不正确时抛出的错误,主要涉及encodeURI()、decodeURI()、encodeURIComponent()、decodeURIComponent()、escape()和unescape()这六个函数。

【错误处理】

即使程序发生错误,也保证不异常中断的机制。

try{
    // 可能发生错误的代码
}catch(err){
    // 只有发生错误时才执行的代码
}finally{
    // 无论是否出错,肯定都要执行的代码
}

使用要点:

使用try包裹的代码,即使不出错,效率也比不用try包裹的代码低;
在try中,尽量少的包含可能无错的代码;
无法提前预知错误类型的错误,必须用try catch捕获;
finally可以省略;

【主体】

(1)Error对象

JS拥有当错误发生时提供错误信息的内置 error 对象,error 对象提供两个有用的属性:name 和 message。

(2)Error的name属性值
在这里插入图片描述
(3)try 和 catch

try 用于定义在执行时进行错误测试的代码块,catch 语句定义当 try 代码块发生错误时,所执行的代码块。
catch 块会捕捉到 try 块中的错误,并执行代码来处理它
注意:JS语句 try 和 catch 是成对出现的,否则会出现报错。

(4)throw

抛出(throw)错误:当错误发生时,当事情出问题时,JavaScript 引擎通常会停止,并生成一个错误消息。描述这种情况的技术术语是:JavaScript 将抛出一个错误,并终止程序执行。

throw 语句允许创建自定义错误,从技术上讲能够抛出异常(抛出错误),异常可以是 JavaScript 字符串、数字、布尔或对象
throw “Too big”; // 抛出文本
throw 500; // 抛出数字

如果把 throw 与 try 和 catch 一同使用,就可以控制程序流并生成自定义错误消息。

(5)通俗理解

①try

try里面的代码错误的时候会报错,但是不会抛出错误,他不会执行错误的代码;而是跳过,try里面后面的代码依然执行不出来,但是,后续的代码还是会执行。在try里面发生错误,不会执行错误后的try里面的代码。那catch什么意思呢?

②catch

当try里面的代码没有错误的时候,catch里面的代码是不会被执行的;当try里面的代码有错误的时候,catch就负责把错的给捕捉到,有一堆错误信息error(error是对象),系统会把错误信息(error.message error.name)封装到一个error对象里面,然后把error对象传到e里面,供抛出异常使用。

catch就是负责捕捉错误的,捕捉错误到程序里面,就不会抛出到控制台里面,也就不会让程序去终止。

(6)finally

finally 语句不论之前的 try 和 catch 中是否产生异常都会执行该代码块。

try {
     // 供测试的代码块
}
 catch(err) {
     // 处理错误的代码块
} 
finally {
     // 无论 try / catch 结果如何都执行的代码块
}

(7)Error的name属性值

接下来依次分析下各个属性取值

①RefereError

     非法引用错误,即引用未定义的变量或函数。

     如果一个变量未经声明就使用的话,就会RefereError;当一个函数未经声明就调用,也会RefereError。

②SyntaxError

     语法错误,即标点符号使用错误
     
③EvalError

     指示 eval() 函数中的错误。更新版本的 JavaScript 不会抛出任何 EvalError,利用SyntaxError 代替。

④RangeError

	  数值超出规定的范围
      一般这种错误也是在递归函数当中出现,接下来先看一个简单的,就可以明白这个问题出现的函数:
     只要一运行这个函数,就会直接报上面的那个错误。原因:这就是因为一个函数一直递归调用自己,无法停止,只有在内存被塞满(内存溢出)的时候,报错才能够停止。所以,有这个报错,先检查一下,是不是条件判断有错误。

⑤TypeError 

     使用的值不在期望值的范围之内,则抛出TypeError错误  
     错误的使用了类型或对象的方法时,变量或参数不是预期类型时发生的错误。比如,对字符串、布尔值、数值等原始类型的值使用new命令,就会抛出这种错误,因为new命令的参数应该是一个构造函数。

⑥URIError

     如果在 URI 函数中使用非法字符,则抛出URIError错误
     URIError对象是 URI 相关函数的参数不正确时抛出的错误,主要涉及encodeURI()、decodeURI()、encodeURIComponent()、decodeURIComponent()、escape()和unescape()这六个函数。

(8)非标准的 Error 对象属性

Mozilla 火狐和 Microsoft 微软定义了非标准的 error 对象属性:

fileName (Mozilla)
lineNumber (Mozilla)
columnNumber (Mozilla)
stack (Mozilla)
description (Microsoft)
number (Microsoft)

注意:它们并不会在所有浏览器中工作,所以要避免在公共网站使用这些非标准的Error对象属性。

throw 和 try…catch 一起使用

/*
异常处理
了解 JavaScript 中程序异常处理的方法,提升代码运行的健壮性。

throw   抛异常
try ... catch   捕获异常
debugger    相当于断点调试

error对象   异常描述

throw
异常处理是指预估代码执行过程中可能发生的错误,然后最大程度的避免错误的发生导致整个程序无法继续运行

*/

function counter(x, y) {
  if (!x || !y) {
    // throw '参数不能为空!';
    throw new Error('参数不能为空!')
  }
  return x + y
}

counter()
/*
总结:
1. `throw` 抛出异常信息,程序也会终止执行
2. `throw` 后面跟的是错误提示信息
3. `Error` 对象配合 `throw` 使用,能够设置更详细的错误信息
*/

function foo() {
  try {
    // 查找 DOM 节点
    const p = document.querySelector('.p')
    p.style.color = 'red'
  } catch (error) {
    // try 代码段中执行有错误时,会执行 catch 代码段
    // catch 拦截错误,提示浏览器提供的错误信息,但是不中断程序的执行 
    // error == { name, message }
    // 查看错误信息
    console.log(error.message)
    // 需要 return 终止代码继续执行
    return
  }
  finally {
    // 不管你的程序对不对,一定会执行
    alert('执行')
  }
  console.log('如果出现错误,我的语句不会执行')
}
foo()
/*
总结:
1. `try...catch` 用于捕获错误信息
2. 将预估可能发生错误的代码写在 `try` 代码段中
3. 如果 `try` 代码段中出现错误后,会执行 `catch` 代码段,并截获到错误信息
*/

关于奇怪的“try catch”
请想一想,getName执行返回的是你的好朋友muzidigbig,还是我们的好朋友xiaohong?

const getName = () => {
  try {
  	console.log(1111)
    return 'muzidigbig'
  } finally {
    return 'xiaohong'
  }
}

getName() // ?

在这里插入图片描述

答案是“muzidigbig”?不是!答案是“xiaohong”。

这是因为在“try….catch….finally”语句中,finally子句无论是否抛出异常都会被执行。另外,如果抛出异常,即使没有catch子句处理异常,finally子句中的语句也会被执行。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐