1、错误调试和处理
1、我们在本篇博客中将会讲述JS中语法错误、运行时错误和他们的处理方法
2、JS中的逻辑错误以及debugger的使用
3、JS中的try catch和finally语句的使用
2、语法错误
1、语法错误就是不符合JS语法的错误,出现语法错误,控制台会尽心报错并告知出错的行号,但是行号不一定准确。
2、常见的错误:
(1)字符的漏写,少写,多写:多数这种错误会提示unexpected token xx,token就是字符串,或者单词,总之token是构成源代码的最小单位,比如一个变量名是一个token,一个符号是一个token。
(2)符号的错误使用:符号的漏写,少写一般会提示:unexpected identifier(意外的标识符),也就说这里少了某个字符,导致下一个语句或者标识符成为了意外。
(3)错误的语句
3、运行时错误(runtime error)
1、运行时错误就是代码没有语法错误,而在运行时候发生的错误,运行时错误是一个统称。
2、ReferenceError错误:变量引用异常触发(reference是参考和引用的意思),比如说变量没有定义直接使用会导致错误。
<script>
console.log(foo);//foo没有定义,这里的定义是变量的声明和初始化
</script>
3、TypeError错误:类型使用错误触发:比如说我们定义了变量a=9,后面忘记a为数值变量,误把a当做函数使用a()。一般有两种情况:
(1)获取未初始化变量的属性和方法:
<script>
var foo;
console.log(foo.length);//foo未初始化,不存在length这个属性
</script>
(2)调用类型错误:
<script>
var foo=9;
foo();//foo是个数值变量,不是函数
</script>
4、RangError错误:不太常见,一般会在递归爆栈时触发,就是递归层数太深,超过浏览器规定的最大递归层数(1024层)
<script>
function foo(){
return foo();
}
</script>
这里有个调用栈的概念,比如说我们计算前n项自然数的和:这里S(5)执行开始过程中,S(4)开始执行,接着是S(3)....但是S(5),S(4),S(3)...都没有结束,必须S(1)结束后,S(2)才会结束,依次类推,所以它们形成了这样有序的等待序列(包括执行等待序列和结束等待序列),我们就称之为调用栈。
function S(n){
if(n===1){
return 1;
}else{
return n+S(n-1);
}
}
递归深度错误解决的方法,使用循环去写。不会出现递归层数过深产生的RangError的错误。
4、如何区分语法错误和运行时错误
1、一个简单的区分方法就是,语法错误是无论如何也不能运行成功,但是运行时错误有可能运行成功。
2、另一个方法就是很多比较高端的编辑器,可以在语法错误时提示高亮,这个是与程序员使用的编辑器和代码书写方式习惯有关的。
5、逻辑错误
1、逻辑错误就是计算结果不符合预期效果,没有发生语法错误和运行时错误。
2、解决逻辑错误的方法,单步调试:在程序的执行的过程中,我们可以添加debugger;这样的代码来作为程序中的断点调试;
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8">
</head>
<body>
<script>
var sum=0;
var i;
debugger;
for(i=1;i<10;i++){
sum+=1;
}
console.log(sum);
</script>
</body>
</html>
在浏览器中打开控制台,转换到sources处,下图所示:
右边有调试的按钮,在watch中可以添加变量和表达式,并在程序执行的过程中,工具会自动监听这些变量的值和表达式的结果,breakPoints是显示你在左侧打了断点后会显示行号和所在行的代码。
6、try catch finally
(1)try catch主要是主动抛出一个错误,去在程序执行的时候做判断,
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8">
</head>
<body>
<script>
function getUserInput(msg){
var input=prompt(msg);
var parsed=parseInt(input);
if(parsed!=parsed){
return input;//如果解析为number为NaN就返回你输入东西
}else{
return parsed;//如果为数字,就返回数字;
}
}
function multiple(a,b){
if((typeof a !='number')||(typeof b!='number')){
throw new Error('argument should all be number');
}
return a*b;
}
function text(){
var c;
var a=getUserInput('请输入一个数字:');
var b=getUserInput('请再输入一个数字:');
c=multiple(a,b);
alert('您输入的两个数字的乘积为:'+c);
}
try {
text();
} catch (error) {
alert('必须输入数字');
text();
}
</script>
</body>
</html>
(2)finally是写在try catch后面,表示无论你try catch的地方怎么执行,最后都要执行finally中的语句,一般finally用来一些清理的工作,而且finally中的return语句是作为最后的返回结果:
function foo(){
try{
throw new Error();
}catch(e){
return 1;
}finally{
return 2;
}
}
foo();//最后执行的结果是2
最后注意的就是try catch语句只能捕捉运行时的错误,语法错误是捕捉不到的。