如何在浏览器上优雅的进行调试

日常开发我们碰到的很多问题,通常我们都会通过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的那行代码上

  • subtree modifications 子节点内容的的修改删除新增(子节点的属性修改不会触发,当前节点的修改不会触发)
  • attribute modifications 当前节点的属性修改删除新增
  • node removal 当前节点被移除

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

spy-debugger 是一个一站式页面调试、抓包工具。远程调试任何手机浏览器页面,任何手机移动端webview(如:微信,HybridApp等)

特性:

  1. 页面调试+抓包
  2. 操作简单,无需USB连接设备
  3. 支持HTTPS。
  4. spy-debugger内部集成了weinrenode-mitmproxyAnyProxy
  5. 自动忽略原生App发起的https请求,只拦截webview发起的https请求。对使用了SSL
    pinning技术的原生App不造成任何影响。
  6. 可以配合其它代理工具一起使用(默认使用AnyProxy) (设置外部代理)

使用教程

1、安装spy-debugger

npm install -g spy-debugger

2、通过spy-debugger相关命令运行插件

相关命令如下

  • spy-debugger 按默认配置启动
  • spy-debugger -p 8888 设置端口号为8888,默认是 9888
  • spy-debugger -e http://127.0.0.1:8888 设置外部代理,默认使用 anyproxy
  • spy-debugger -i true 是否允许weinre监控iframe加载的页面,默认是 false
  • spy-debugger -w true设置页面内容为可编辑模式,默认是 false
  • spy-debugger -b false是否只拦截浏览器发起的https请求,默认是 true

有些浏览器发出的connect请求没有正确的携带userAgent,这个判断有时候会出错,如UC浏览器。这个时候需要设置为false。大多数情况建议启用默认配置:true,由于目前大量App应用自身(非WebView)发出的请求会使用到SSL pinning技术,自定义的证书将不能通过app的证书校验。

  • spy-debugger -c true是否允许HTTP缓存 ,默认是 false

3、手机与电脑在同一个局域网下开启,手机开启网络代理,例如上图,此时我要在手机配置代理192.168.31.114:9888

4、手机安全证书 -> https://spydebugger.com/cert

注意⚠️:一定开启了手机网络代理之后再去打开这个域名哈,直接打开域名会被重定向到18🈲,别说我没提醒你

完成上述操作即可进行代理了,通过浏览器打开 http://127.0.0.1:50470

参考文档 --> spy-debugger: spy-debugger 是一个一站式页面调试、抓包工具

 

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值