前言
本系列记录和整理前端的基础知识,希望通过系统性地学习来巩固自己对前端的理解。以《高级程序设计》第 4 版(红宝书),作为学习主体,结合自己工作中遇到的实际案例来了解、理解文中的基础知识点。接下来就一起来看看吧
调试技术
常用技巧
罗列一些,自己在平时开发过程中经常使用的调试技巧,有效的提高自己的开发效率。
- 代码块的使用
- 快速获取 DOM 节点引用
- show changes 查看 css 改动,有时为了方便,我们会选择直接在浏览器,当调试完后如何查看我们改了哪些样式呢?
- commond + shift + p 唤起面板, 输入 show changes 查看改动 diff
Debug JavaScript
单步全文调试代码
用的最多的还是使用 Debug JavaScript。可以打开 debug demo
来看下如何给 js 文件设置断点。当我们点击按钮时会执行 onClick 函数
function onClick() {
// 执行函数1
if (inputsAreEmpty()) {
label.textContent = 'Error: one or both inputs are empty.';
return;
}
// 执行函数2
updateLabel();
}
首先我们将断点设置在 15
行。此处是函数执行的入口处。我们可以通过操作这五个按钮来进一步 Debug 代码
- 运行代码直到下一个断点,如果后续无断点则一直运行到结束。
- 单步执行到下一个函数执行前。这里的下一个函数指的是同一作用域中。比如 onClick 函数中调用了两个函数,如果我们点击 2 按钮,我们应该会跳转到 updateLabel() 这一行。
3. 进入下一个函数。也是针对同一作用域下,下一个要执行的函数是 inputsAreEmpty, 当我们点击 3 会执行到 inputAreEmpty 函数的第一行。
- 跳出当前函数。当我们发现当前函数没有我们 Debug 信息,我们需要跳出当前作用域进入父级作用域继续往下 Debug。紧跟第 3 步如果我们想要跳出 inputsAreEmpty 就可以点击按钮 4 。此时直接来到父作用域的下一步。
- 如果你想完整地走一遍函数的执行流程,你可以一直点按钮 5。注意如果函数有 return 值的函数,return 值也算一步,有时候会看见在同一行断点停了两次。
检查变量
- 方式一: 在 Scope 面板中查看当前作用域和作用域链上的变量
- 方式二: 在 watch 面板输入要监听的变量
- 方式三: 直接在 console 中输入当前作用域可访问的变量。此方法在变量比较多的时候比较有用,也可以自行根据当前作用域变量进行一些运算。
- 查看调用栈:
- 点击调用栈可以查看其作用域的变量
- 当一个方法有多个入口共同调用,可以通过调用栈来定位到触发函数的起源在哪,有利于我们判断。
修复
当我们发现 bug 可以直接在文件中修改,不需要刷新,在此进行点击事件进行结果验证。如果符合预期后将代码更新同步到自己本地的代码中。
错误
通过调试我们可以快速定位到错误位置,接下来我们来看看常见的有哪些错误,如何进行处理,以及如何抛出错。
错误类型
代码执行过程中会发生各种类型的错误。每种类型都会对应一个错误发生时抛出的错误对象。ECMA-262定义了以下 8 种错误类型:
- Error 基类,其他错误类型继承该类型。所有错误类型都共享相同的属性。
- InternalError 类型。浏览器抛出,如栈溢出。
- EvalError 类型。使用 eval() 异常抛出。
- RangeError 类型。数值越界时抛出。
- ReferenceError 类型。找不到对象时发生。
- TypeError 类型。主要发生在变量不是预期类型。
let o = new 10; 'name' in true; Function.prototype.toString.call('name');
- URIError 类型。在使用 encodeURI() 或 decodeURI() 传入格式错误的 URI 时发生。
错误捕获
- window error 监听运行时报错。在任何错误发生时,无论是否是浏览器生成的,都会触发。
window.addEventListener('error', (msg,url,lineNo,columnNo,e) => {
// ...上报错误
})
- promise reject 未捕获。
window.addEventListener('unhandledrejection',(event) => {
// 报错原因,当前路径,报错时间
const { message,config:{method,url} } = event.reason
// ...上报错误
})
- try catch 捕获同步代码错误
// 保存原生的 addEventListener 事件
const originAddEventListener = EventTarget.prototype.addEventListener
// 重写原生的监听事件
EventTarget.prototype.addEventListener = (type,listener,options) => {
const wrappedListenner = (...args) => {
try {
return listener.apply(this,args)
} catch (error) {
const { name,message } = error
// ...上报错误
throw error
}
}
return originAddEventListener.call(this,type,wrappedListenner,options)
}
抛出错误
throw new Error('something bad happened')
throw new SyntaxError('something bad happened')
throw new TypeError('something bad happened')
throw new RangeError('something bad happened')
throw new ReferenceError('something bad happened')
识别错误
- 静态代码分析, 推荐使用 TypeScript
- 类型转换错误, 通常是自动改变某个值的数据类型的操作符造成,如使用 (==) 或 (!=) 。以及 if、for 或 while 中使用非布尔值。
- 数据类型错误, 进行类型检查保证安全
function getQueryString(url) {
if(typeof url === 'string') {
let pos = url.indexOf('?')
if(pos > -1) {
return url.substring(pos + 1)
}
}
return '';
}
小结
对于今天复杂的 Web 应用程序而言,js的错误处理和快速定位十分重要。梳理了浏览器的常用的 Debug 方法,一些常出现的错误类型。在平时开发中有意识地去判断是否要进行错误的捕获,以及有效的错误的识别有助于写出更健壮的代码。
参考
《高级程序设计》第 4 版
Chrome Developers
声明:本文仅供个人学习使用,来源于互联网,本文有改动,本文遵循[BY-NC-SA]协议, 如有侵犯您的权益,请联系本站,本站将在第一时间删除。谢谢你
原文地址:前端基础知识-错误调试和处理