重温js—— 错误处理

简介: 上面的代码中,我们定义了一个变量,然后当中函数的方法来调用,最后输出一个结果。但是运行期间却报错了,并且下面的代码也是没有执行的,原因是代码报错了会阻止程序的运行。我们大家都知道js的解释性语言,代码解释一句然后执行一句,所以后面的代码是不能够直接执行的。

在开发的过程中,遇见错误是很正常的。但是我要知道的是,错误发生的原因和如何去处理错误呢?


出现错误的原因


在代码的书写中,出现的原因有,代码本身书写错误和运行错误


书写错误


89667a3731394425bd60c348af10e181.png


主流的代码编辑器,如果你的代码是编写错误,那么编辑器一般会提示你报错了,并且给出修改的建议。


运行错误


代码运行错误分为运行时候报错和预期结果不对


运行时报错


代码的书写中,我们可能没有报错,但是代码在执行的过程中发现错误了。


fd626683fd354b5daced6d55a487f26f.png


上面的代码中,我们定义了一个变量,然后当中函数的方法来调用,最后输出一个结果。但是运行期间却报错了,并且下面的代码也是没有执行的,原因是代码报错了会阻止程序的运行。我们大家都知道js的解释性语言,代码解释一句然后执行一句,所以后面的代码是不能够直接执行的。


预期结果不符合


这个错误是比较难发现的,代码能够正常运行,只是结果不对,我们的逻辑不对。如:


function sum (a, b){
  return a + b;
}
// 这里有好多代码得出的1 和 '2'
const res  = sum(1, '2');
console.log(res);

5c46f02fc9a44f93a26d15be42ddfc66.png


上面的代码我们代码本身没有错,运行也没有报错,只是结果不对,那对于这种问题我们怎么来解决呢?


解决预期不符合的方法


解决这种预期不符合的方法有以下两种, console.log 关键地方输出 和debugger来调试


console.log 关键地方输出


使用的方式很简单,在觉得有问题的地方,打印出结果来看就行。


09b2b54cf95042c2a51b02e294de0b57.png


对于这种方法,个人觉得并不是很好,如果代码量多,并且调用的地方多,console.log 就要写很多遍,找到问题后,又需要把这个删除,感觉工作量有点大。


debugger来调试


其实启动debugger的方式很简单,在我们的代码中直接书写debugger或者在编辑器的右边打红色的点(vscode为例),然后运行debugger模式。就可以启动debugger;


c9f37e50786f445381cf73dfbb739a67.gif


这个是启动node环境的,还可以在浏览器环境启动。启动的方式也是类似。debugger可以在右侧看到你当前变量的值和类型。非常的方便对于调试。


抛出错误


对于我们已经知道代码会报错,我们可以抛出错误。让使用的人知道。


语法


throw new 错误对象


常见的错误对象有:


48fe0f004e5d4f1ab5587703cddfd5a5.png


详情请查看


我们可以把我们的代码改造一下:


function sum (a, b){
  if(isNaN(a)){
    throw new TypeError('a must be a number')
  }
  if(isNaN(b)){
    throw new TypeError('b must be a number')
  }
  return a + b;
}
const res  = sum(1, '2');
console.log(res);

f681e3cbd8034f709e8d54f0fb49e188.png


错误堆栈信息


错误堆栈的运行过程是这样的,全局 ---> 局部1 --->局部2. 然而错误的显示信息是 局部2--->局部1--->全局,所以在报错信息的第一行就是我们实际代码throw 的 error。


捕捉错误


既然我们可以手动抛出错误,那么必然也是可以进行手动来捕捉错误的。


语法


try{
// 代码块1,需要捕捉的代码
}catch(错误对象){
// 报错后执行的代码块
}finally{
// 无论报不报错都会执行
}


catch 和 finally 可以省略。


改造一下代码。


function sum(a, b) {
  if (typeof a !== 'number') {
    throw new TypeError('a must be a number')
  }
  if (typeof b !== 'number') {
    throw new TypeError('b must be a number')
  }
  return a + b;
}
try {
  const res = sum(1, '2');
  console.log(res);
} catch (err) {
  console.log(err);
} finally {
  console.log('一定执行的代码')
}
console.log('其他全局的代码');

223cc8cb2ac04e929a4a5380468e6c66.png

相关文章
|
Web App开发 移动开发 JavaScript
重温js—— 事件循环
大家都知道,js是单线程的语言。为啥要设置成单线程的呢? 不妨大家想一想,如果js是多线程的语言,一个线程来操作删除dom,一个线程来新增dom.那么这两个谁能先完成?结果就会变得不可控制。但是这里有的人肯定会说,html5提出了workers可以来启动多线程。没错,workers是可以用于启动多线程,在worker线程中你可以运行任何你喜欢的代码,不过有一些例外情况。比如:在worker内,不能直接操作DOM节点,也不能使用window对象的默认方法和属性,这也是存在一些弊端的(本质上也还是单线程)。
重温js—— 事件循环
|
JavaScript Java Go
重温js——作用域和作用域链
js代码执行,会在call stack创建对应的作用域(执行上下文),然后每一个上下文中会有一个VO来保存当前作用域的变量. 但是VO中如果会创建函数,那么函数中有一个额外的属[[scoped]]会指向栈中最顶层的VO(AO);
重温js——作用域和作用域链
|
JavaScript Go
重温js——执行上下文
在函数的那一张中,提到了全局环境和局部环境的概念,就是说在函数的执行过程中,函数内部的环境和外面是独立的,只是说函数内部可以使用外面全局环境的变量或者在调用全局函数的方法。在此,来总结一下js的执行环境。
重温js——执行上下文
|
JavaScript 前端开发
重温js——属性描述符
我们会发现,当我们去改变属性赋值的时候,会自动执行set函数,相当于是通知了set函数。属性取值的时候会自动的执行get函数,自动通知get函数。正是因为有这个自动通知的功能,vue2中的响应式系统就是基于Object.defineProperty()来实现对象的响应的。
重温js——属性描述符
|
JavaScript
重温js——原型和原型链
我们在前文说到,所有的对象都是通过new 函数来创建的,所有的函数也都是对象 . 那么问题来了,Function也是一个函数,那么他是怎么来的呢?(这个问题是不是类似有点像先有鸡和先有蛋的感觉)但是Function函数是在js引擎启动的时候,就直接把Function放入到内存中的.
重温js——原型和原型链
|
JavaScript 前端开发
重温js——正则表达式
正则表达式是一种规则,在语法上各个语言都是一样的,有点是通用性很高,缺点是在平常开发中使用的频率并不是很高,主要使用的范围在用于判断字符串里面的规则。
重温js——正则表达式
|
JavaScript
重温js——构造函数基础
在上面的代码中,我们可以创建多个对象,使用函数的方式来创建的对象。(但是这两个对象是不一样的,每一次都创建一个新的对象)可以方便许多,除了上面的方法外,还有一种构造函数的方式来创建对象。
重温js——构造函数基础
|
JavaScript
重温js——函数表达式和this
我们知道a 里面保存的是函数的引用地址,那么函数的调用是使用 () 来进行调用,保存到某个变量中的函数地址,直接 a() 就能调用该函数了。
重温js——函数表达式和this
|
JavaScript
重温js——函数基础
函数的作用,减少重复代码,实现代码的解耦。把某个功能点给抽离出来。使得代码阅读增加
重温js——函数基础
|
存储 JavaScript
重温js——数组
push 是在数组的末尾添加新的数据,数据可以是多个,会依次添加到数组的末尾
重温js——数组