如何在浏览器上优雅的进行调试 | 您所在的位置:网站首页 › 浏览器控制台指令 › 如何在浏览器上优雅的进行调试 |
日常开发我们碰到的很多问题,通常我们都会通过console或debugger 去快速定位排查问题,会定位问题可以节省很多时间。也就是我经常说的工欲善其事,必先利其器。所以在这和大家发现几个容易让大家忽略的调试技巧; 控制台打印在平常的开发中我们应该常常用到下面这些命令去进行调试 console.log(‘Hello World!’); // 最最常用 console.info(‘Something happened…’); // 用于打印提示性信息 console.warn(‘Something warn happened…’); // 用于打印警示信息 console.error(‘Something error happened…’); // 用于打印错误信息但是仅此而已?下面👇展示几个你不知道或者你常常会忽略的技巧 1、console.trace() 如果你想知道消息是哪里打印出来的,使用console.trace()来获取要打印的数据的stacktrace; 2、console.time() && console.timeEnd() 如果你想分析函数的性能,可以使用console.time()来计时,console.timeEnd()来结束计时,控制台会打印出两次之间的时间差; 注:两个方式需要传入一个字段名,以此来区分多个计时器,当你同一个方法在执行期间多次传人则只有第一个会生效; 3、console.count 如果你想记录一下一个函数被调用了多数次的话可以使用这个方法; 4、console.assert 如果你想某些为假的条件下输出消息,而不是用if-else时可以使用这个方法; 注:nodejs下不支持这种写法,会报错; 5、console.group() & console.groupEnd() 如果你想把所有的console.log全部聚合在一起的话可以使用这个方法; 6、console.dir() 打印出该对象的所有属性和属性值,console.dir和console.log的区别并不明显,唯一的区别就是在dom节点的打印方面,log直接展示对应的元素,而dir是以对象的形式把属性和值进行呈现 demo let timeDemo = async () => { console.time(); setTimeout(() => { console.log('3000 timeout') console.timeEnd(); }, 3000) } let traceDemo = () => { console.trace('trace') }; let assertDemo = (mahkSex) => { let isTrue = mahkSex === 'box'; console.assert(isTrue, 'mahk is a box'); }; let groupDemo = () => { console.group() console.log('i in groud 1'); console.log('i in groud 2'); console.log('i in groud 3'); console.groupEnd(); } let demo = (type) => { if (type === 'trace') { traceDemo(); } if (type === 'time') { timeDemo(); } if (type === 'assert') { assertDemo('girl'); assertDemo('box'); } if (type === 'group') { groupDemo(); } console.count('dome这个方法被调用的次数:'); }; demo('trace') // demo('time') // demo('assert') // demo('group') // let test = { a: 1 }; // console.log(test.a); // console.log(test); // test.a++; // console.log("%c这是一段被修改样式的输出文字", "color: blue; font-size: x-large; background: #ddd");PS:console.log 打印的值不准确问题 有些时候在使用·console.log() 打印对象的时候,打印出来的值不符合预期。这是为什么呢? let test = { a: 1 }; console.log(test.a); console.log(test); test.a++;有一种说法是:console.log() 是一个异步的方法,浏览器在处理的时候对于这种读取 i/o 的操作一般会放到比较靠后的位置去处理。所以有些时候打印出来的值不符合预期。 还有一种说法是,当在打印一个对象的时候,由于对象中的值是引用的内存中的值,所以就会存在当打印对象的时候,当引用到对象中的值的时候,对象中的值已经发生变化了。所以才会存在打印结果与预期不一致的情况。 在《你不知道的javascript中卷》第二部分异步和性能1.1节异步控制台部分有提及: 并没有什么规范或一组需求指定console.* 方法族如何工作——它们并不是JavaScript 正式的一部分,而是由宿主环境(请参考本书的“类型和语法”部分)添加到JavaScript 中的。因此,不同的浏览器和JavaScript 环境可以按照自己的意愿来实现,有时候这会引起混淆。 尤其要提出的是,在某些条件下,某些浏览器的console.log(..) 并不会把传入的内容立即输出。出现这种情况的主要原因是,在许多程序(不只是JavaScript)中,I/O 是非常低速的阻塞部分。所以,(从页面/UI 的角度来说)浏览器在后台异步处理控制台I/O 能够提高性能,这时用户甚至可能根本意识不到其发生。 console.log打印出来的内容不一定正确。一般对于普通类型number、string、boolean、null、undefined的输出是可信的。但对于Object等引用类型来说,则就会出现上述异常打印输出。 所以对于一般基本类型的调试,调试时使用console.log来输出内容时,不会存在坑。但调试对象时,要么你就把对象深拷贝一下,要么你就debugger,最好还是使用断点(debugger)这样的方式来调试更好。 debugger断点调试了解source面板 断点类型 1、行断点:代码运行到当前行之前暂停执行(常用) 在源代码添加debugger关键字 或者点击Sources面板中的源代码的行号 2、条件行断点:当满足条件时才会触发该断点 右击Sources面板中的源代码的行号,选择“Add conditional breakpoint” 3、dom节点断点 当我们进行ui问题排查时,例如ui为啥属性突然发生变更时,就可以使用这个方法,切换到Elements页签,在想要添加断点的DOM节点上右键点击,在最下边的Break on菜单项可以找到这三个选项. 当我们的脚本触发了DOM的修改时,devtools会直接跳转到Source页签并定位到修改DOM的那行代码上 4、异常事件断点 当我们不知道哪里会代码异常时开启异常事件断点,能帮助我们自动定位到异常问题,及时修复 4、XHR/Fetch 断点(感觉不是很实用) 在页面发出XHR或Fetch请求前加断点 5、Event Listener 事件监听断点 可以在所有类型的事件函数被出发前加断点 6、Function 函数断点 把想调试的函数名作为参数,调用debug()函数,可以在每次执行该函数前暂停执行代码 参考文档 --> 浏览器原理与使用上 - 使用篇: - 知乎 demo let demoObject_1 = { a: 1, b: 'test', } let demoObject_2 = { a: 1, b: 'test', } const demoFunction_1 = () => { let a = 2; console.log(demoObject_1); demoObject_1.a++; demoObject_1.a++; demoObject_1.a++; console.log(demoObject_1); demoObject_1.a++; } const demoFunction_2 = () => { let a = 2; console.log(demoObject_2); demoObject_2.a++; console.log(demoObject_2); demoObject_1.a++; } const demo1 = () => { demoFunction_1(); demoFunction_2(); } demo1(); chrome常被忽略的奇技淫巧1、修改请求参数重新发起 然后复制于控制台然后修改请求参数重新发起接口请求 2、控制台中$的使用 $_:可以返回控制台上次输出对象 $0、$1、$2、$3、$4:$0、$1、$2、$3 和 $4 命令用作在 Elements 面板中检查的最后五个 DOM 元素或在 >Profiles 面板中选择的最后五个 JavaScript 堆对象的历史参考。$0 返回最近一次选择的元素>或 JavaScript 对象,$1 返回仅在最近一次之前选择的元素或对象,依此类推。 $(selector) :返回带有指定的 CSS 选择器的第一个 DOM 元素的引用,此函数等同于调用document.querySelector() 函数。 $$(selector) :返回与给定 CSS 选择器匹配的元素数组。此命令等同于调用document.querySelectorAll()。 3、使用css样式可以用来更改控制台的输出样式 CSS 格式说明符%c可以修改在控制台中输出的样式。以你要修饰的文字配上占位符开始,然后在第二个参数中写上你要展示的风格 console.log("%c这是一段被修改样式的输出文字", "color: blue; font-size: x-large; background: #ddd");4、Filter过滤 排除过滤(反向搜索)在要搜索的字符前加-,表示反向搜索 多条件搜索每个搜索间用 空格斜杆空格隔开 / 支持正则搜索,直接输入正则即可5、直接在控制台导入cdn资源包 GitHub - pd4d10/console-importer: Easily import JS and CSS resources from Chrome console. 通过引入这个插件即可按需在控制台引入cdnjs 例如 我绝的这个moment-js这边包的方法挺好的,想要引用,就可以进行如下操作 6、通过浏览器配置,解决跨域问题(修改浏览器属性解决浏览器安全策略拦截问题) 在Google启动文件属性中增加目标项中增加--disable-web-security --user-data-dir,重新打开浏览器即可临时本地浏览器跨域问题 什么是spy-debugger spy-debugger 是一个一站式页面调试、抓包工具。远程调试任何手机浏览器页面,任何手机移动端webview(如:微信,HybridApp等) 特性: 页面调试+抓包操作简单,无需USB连接设备支持HTTPS。spy-debugger内部集成了weinre、node-mitmproxy、AnyProxy。自动忽略原生App发起的https请求,只拦截webview发起的https请求。对使用了SSL pinning技术的原生App不造成任何影响。可以配合其它代理工具一起使用(默认使用AnyProxy) (设置外部代理)使用教程 1、安装spy-debugger npm install -g spy-debugger 2、通过spy-debugger相关命令运行插件 相关命令如下 spy-debugger 按默认配置启动spy-debugger -p 8888 设置端口号为8888,默认是 9888spy-debugger -e http://127.0.0.1:8888 设置外部代理,默认使用 anyproxyspy-debugger -i true 是否允许weinre监控iframe加载的页面,默认是 falsespy-debugger -w true设置页面内容为可编辑模式,默认是 falsespy-debugger -b false是否只拦截浏览器发起的https请求,默认是 true有些浏览器发出的connect请求没有正确的携带userAgent,这个判断有时候会出错,如UC浏览器。这个时候需要设置为false。大多数情况建议启用默认配置:true,由于目前大量App应用自身(非WebView)发出的请求会使用到SSL pinning技术,自定义的证书将不能通过app的证书校验。 spy-debugger -c true是否允许HTTP缓存 ,默认是 false3、手机与电脑在同一个局域网下开启,手机开启网络代理,例如上图,此时我要在手机配置代理192.168.31.114:9888 4、手机安全证书 -> https://spydebugger.com/cert 注意⚠️:一定开启了手机网络代理之后再去打开这个域名哈,直接打开域名会被重定向到18🈲,别说我没提醒你 完成上述操作即可进行代理了,通过浏览器打开 http://127.0.0.1:50470 参考文档 --> spy-debugger: spy-debugger 是一个一站式页面调试、抓包工具
|
CopyRight 2018-2019 实验室设备网 版权所有 |