一、Javascript常见的代码错误类型

Javascript错误分为两种:
(1)代码错误:这种错误浏览器会报错,可以根据错误类型去排错
(2)逻辑错误:这种错误浏览器不会报错,但是可以使用断点进行调试排错

ECMS中定义了以下七种错误类型,并在错误发生时抛出不同的错误对象。

  1. Error
    Error是基类型,其他错误类型都是继承该类型,因此,所有错误类型都是共享相同的属性(所有错误对象上的方法都是这个默认类型定义的方法)。
    浏览器很少会抛出Error类型的错误,该类型主要用于开发者抛出自定义错误。(如:throw new Error(输出错误信息))。拦截器/导航守卫中也经常会使用到.
  2. SyntaxError(语法错误)
    当错误的使用已经预定义的语法时会抛出此错误。
    a.变量名不符合规范
    b.缺少括号引发的语法错误
    c.用let、const声明重复变量/常量
//a:变量名不符合规范
var 1s;//Uncaught SyntaxError: Invalid or unexpected token
var c=1;
//b:缺少括号引发的语法错误
console.log 'song')
VM180:1 Uncaught SyntaxError: Unexpected string
//c:用let、const声明重复变量/常量
const c=2;//Uncaught SyntaxError: Identifier 'c' has already been declared
  1. TypeError(类型错误)
    当值不是预期数据类型、调用无效方法时都会抛出此错误。
    a:new后面接字符串、数值、布尔值等(new后面应该接构造函数)
    b:调用不存在的方法
//a:new后面接字符串、数值、布尔值等(new后面应该接构造函数)
new 'song';//Uncaught TypeError: "song" is not a constructor
new 12;//Uncaught TypeError: 12 is not a constructor
new true;//Uncaught TypeError: true is not a constructor
//b:调用不存在的方法
var obj={name:"song",sex:2,};
obj.play();//Uncaught TypeError: obj.play is not a function
  1. ReferenceError(引用错误)
    当找不到变量的引用、在变量作用域范围之外使用变量、使用未声明的变量时、在暂时性死区期间使用变量时都会抛出此错误。
str=2;
let str=1;//Uncaught ReferenceError: Cannot access 'af' before initialization
  1. RangeError(范围错误)
    数组的长度为负数、将变量设置在其限定的范围之外、将值传递给超出范围的方法、调用一个不会结束的递归函数时就会抛出此错误。
var a=new Array(-1);//Uncaught RangeError: Invalid array length
  1. URIError( URI 错误)
    当 URI 的编码和解码出现问题时,会抛出 URIError。JavaScript 中的 URI 操作函数包括:decodeURI、decodeURIComponent 等。如果使用了错误的参数(无效字符),就会抛出 URIError。
decodeURI("%2");//Uncaught URIError: URI malformed
  1. EvalError(Eval 错误)
    当 eval() 函数调用发生错误时,会抛出 EvalError。不过,当前的 JavaScript 引擎或 ECMAScript 规范不再抛出此错误。但是,为了向后兼容,它仍然是存在的。
补充:InternalError(内部错误)

非ECMAScript标准,请尽量不要在生产环境中使用它!
InternalError 对象表示出现在 JavaScript 引擎内部的错误(工作负载突然激增时:如当它有太多数据要处理并且堆栈增长超过其关键限制时)。示例场景通常为某些成分过大,例如:

"InternalError: too much recursion"(内部错误:递归过深)。
"InternalError: too many switch cases"(过多case子句);
"InternalError: too many parentheses in regular expression"(正则表达式中括号过多);
"InternalError: array initializer too large"(数组初始化器过大);

二、Javascript异常处理

1.异常处理语句

你可以用 throw 语句抛出一个异常,并且用 try…catch…finally 语句捕获处理它。

throw 语句

使用throw语句抛出一个异常。当你抛出异常,你规定一个含有值的表达式要被抛出。

throw expression;

你可以抛出任意表达式而不是特定一种类型的表达式。下面的代码抛出了几个不同类型的表达式:

throw "Error2";   // String type
throw 42;         // Number type
throw true;       // Boolean type
throw {toString: function() { return "I'm an object!"; } };

try…catch 语句

如果 try 代码块中的语句(或者try 代码块中调用的方法)一旦抛出了异常,那么执行流程会立即进入catch 代码块。如果 try 代码块没有抛出异常,catch 代码块就会被跳过。

//1.自定义一个异常处理函数
function logMyErrors (message){
  this.message=message;
  this.name="logMyErrors";
  alert(message);
};
//2.自定义一段处理程序,报错的话抛出异常
function getMonthName(mo) {
  mo = mo - 1; // Adjust month number for array index (1 = Jan, 12 = Dec)
  var months = ["Jan","Feb","Mar","Apr","May","Jun","Jul",
                "Aug","Sep","Oct","Nov","Dec"];
  if (months[mo]) {
    return months[mo];
  } else {
    throw "InvalidMonthNo"; //throw keyword is used here
  }
}
//3.在try语句块中执行那段处理程序,用catch语句捕获异常信息作为参数传递给异常处理函数处理
try { // statements to try
  monthName = getMonthName(19); // function could throw exception
}
catch (e) {
  monthName = "unknown";
  logMyErrors(e); // pass exception object to error handler -> your own function
}

finally语句

finally 代码块总会紧跟在 try 和 catch 代码块之后执行,但会在 try 和 catch 代码块之后的其他代码之前执行。
finally块无论是否抛出异常都会执行。如果抛出了一个异常,就算没有异常处理,finally块里的语句也会执行。

你可以用finally块来令你的脚本在异常发生时优雅地退出;

try {
        //需要运行的代码 使用throw语句抛错。
    }catch (err) {
        //捕获错误代码
    }finally{
        //无论try和catch的结果如何,都正常执行的代码
    }

ps:catch 和 finally 语句不是必须的,但一条 try 语句中至少使用一个catch 或 finally 语句。