Files
knowledge-kit/Chapter2 - Web FrontEnd/2.24.md
2020-02-25 17:46:51 +08:00

267 lines
11 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Chrome 调试技巧
> **写在前面**
> Chrome 有非常强大的调试功能
> 本文包括浏览器调试不包括web移动端调试。
> 本文调试均在chrome浏览器进行
### alert
这个不用多说了,不言自明
### console
#### 基本输出
想必大家都在用console.log在控制台输出点东西其实console还有其它的方法
```
console.log("打印字符串");//在控制台打印自定义字符串
console.error("我是个错误");//在控制台打印自定义错误信息
console.info("我是个信息");//在控制台打印自定义信息
console.warn("我是个警告");//在控制台打印自定义警告信息
console.debug("我是个调试");//在控制台打印自定义调试信息
cosole.clear();//清空控制台(这个下方截图中没有)
```
![console](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/2019-01-15-01.png)
注意上面输出的error和throw出的error不一样前者只是输出错误信息无法捕获不会冒泡更不会中止程序运行。
#### 格式化输出
除此以外console还支持自定义样式和类似c语言的printf形式
```
console.log("%s年",2016);//%s表示字符串
console.log("%d年%d月",2016,11);//%d表示整数
console.log("%f",3.1415926);//%f小数
console.log("%o",console);//%o表示对象
console.log("%c自定义样式","font-size:30px;color:#00f");
console.log("%c我是%c自定义样式","font-size:20px;color:green","font-size:10px;color:red");
```
![console](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/1460000016256735.png)
<todo>
#### DOM输出
下面几个比较简单的,就不举例子了,简单说一下:
```
var ul = document.getElementsByTagName("ul");
console.dirxml(ul); //树形输出table节点即<table>和它的innerHTML由于document.getElementsByTagName是动态的所以这个得到的结果肯定是动态的
```
![console](https://github.com/FantasticLBP/knowledge-kit/tree/master/assets/1460000016256736.png)
#### 对象输出
```
var o = {
name:"Lily",
age: 18
};
console.dir(obj);//显示对象自有属性和方法
```
![console](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/1460000016256737.png)
对于多个对象的集合,你可以这样,输出更清晰:
```
var stu = [{name:"Bob",age:13,hobby:"playing"},{name:"Lucy",age:14,hobby:"reading"},{name:"Jane",age:11,hobby:"shopping"}];
console.log(stu);
console.table(stu);
```
![console](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/1460000016256738.png)
#### 成组输出
```
//建立一个参数组
console.group("start"); //引号里是组名,自己起
console.log("sub1");
console.log("sub1");
console.log("sub1");
console.groupEnd("end");
```
![console](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/1460000016256739.png)
#### 函数计数和跟踪
```
function fib(n){ //输出前n个斐波那契数列值
if(n == 0) return;
console.count("调用次数");//放在函数里,每当这句代码运行输出所在函数执行次数
console.trace();//显示函数调用轨迹(访问调用栈)
var a = arguments[1] || 1;
var b = arguments[2] || 1;
console.log("fib=" + a);
[a, b] = [b, a + b];
fib(--n, a, b);
}
fib(6);
```
![console](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/1460000016256740.png)
Chrome开发者工具中的Sources标签页也在Watch表达式下面显示调用栈。
#### 计时
```
console.time() //计时开始
fib(100); //用上述函数计算100个斐波那契数
console.timeEnd() //计时结束并输出时长
```
![console](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/1460000016256741.png)
断言语句这个c++调试里面也经常用到。js中当第一个表达式或参数为true时候什么也不发生为false时终止程序并报错
```
console.assert(true, "我错了");
console.assert(false, "我真的错了");
```
![console](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/1460000016256742.png)
#### 性能分析
```
function F(){
var i = 0;
function f(){
while(i++ == 1000);
}
function g(){
while(i++ == 100000);
}
f();
g();
}
console.profile();
F();
console.profileEnd();
```
![console](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/1460000016256743.png)
Chrome开发者工具中的Audits标签页也可以实现性能分析。
### debugger
这个重量级的是博主最常用的可能是c++出身对于单步调试由衷的热爱。单步调试就是点一下执行一句程序并且可以查看当前作用域可见的所有变量和值。而debugger就是告诉程序在那里停下来进行单步调试俗称断点。
![debugger](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/1460000016256744.jpeg)
右边按钮如下:
- Pause/Resume script execution暂停/恢复脚本执行(程序执行到下一断点停止)。
- Step over next function call执行到下一步的函数调用跳到下一行
- Step into next function call进入当前函数。
- Step out of current function跳出当前执行函数。
- Deactive/Active all breakpoints关闭/开启所有断点(不会取消)。
- Pause on exceptions异常情况自动断点设置。
其实右侧还有很多强大的功能
![debugger](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/1460000016256745.png)
- WatchWatch表达式
- Call Stack: 栈中变量的调用,这里是递归调用,肯定是在内存栈部分调用。
- Scope当前作用域变量观察。
- BreakPoints当前断点变量观察。
- XHR BreakPoints面向Ajax专为异步而生的断点调试功能。
- DOM BreakPoints主要包括下列DOM断点注册方式见下图
1. 当节点属性发生变化时断点Break on attributes modifications
2. 当节点内部子节点变化时断点Break on subtree modifications
3. 当节点被移除时断点Break on node removal
![debugger](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/1460000016256746.png)
- Global Listeners全局事件监听
- Event Listener Breakpoints事件监听器断点列出了所有页面及脚本事件包括鼠标、键盘、动画、定时器、XHR等等。
### chrome中的调试技巧
1. DOM元素的控制台书签
Chrome开发者工具和Firebug都提供了书签功能用于显示你在元素标签页Chrome或HTML标签页Firebug中最后点击的DOM元素。如果你依次选择了A元素、B元素和C元素那么&dollar;0 表示C元素&dollar;1 表示B元素&dollar;2 表示A元素。这个和正则表达式的&dollar;符号类似,不过顺序不同)
1. 如果你想调试f函数用debug(f)语句可以增加这种断点。
2. Sources标签页左侧面板上有一个代码片段Snippet子标签页可用于保存代码片段帮你调试代码。
3. 可以用Chrome开发者工具Sources标签页中的格式化按钮Pretty Print Button格式化压缩后的代码。
4. 在Network面板选择一个资源文件右键Copy Response可快速复制响应内容。
5. 利用媒体查询这个主要是在Device Mode调节不同的分辨率显示。
6. 选择Elements按 Esc > Emulation > Sensors进行传感器模拟。
7. 点击渐入效果样式图标(紫色图标),可以预览动画效果,并可对相应的贝塞尔曲线(cubic-bezier)进行调节动画效果。
8. 在Source中按住Alt键并拖动鼠标进行多列内容选择。
9. Elements面板右键执行DOM元素节点选择Force Element State或者点击右侧Toggle Element State图标可以出发伪类。
10. Network面板中选择一张图片在右侧图片上鼠标右键选择copy it as a Data URI,就可以获取图片的Data URL (base64编码)。
11. 通过按住Ctrl键可以添加多个编辑光标同时对多处进行编辑。按下Ctrl + U可以撤销编辑。
12. Elements面板右侧的Style编辑器中点击颜色十六进制编码前的小色块会弹出一个调色板。
13. 按下Alt键并且鼠标双击选择DOM元素前面的箭头就会展开该DOM元素下的所有字节点元素.
14. 快捷键:
- **快速定位到行:**快捷键`Ctrl+O`(Mac:`CMD+O`),输入:行号:列号 来进行定位
- **元素搜索:**快捷键`Ctrl+F`(Mac:`CMD+F`),试试在搜索栏输入ID选择符或者类选择符就可以定位到元素啦
### 调试过程注意事项
1.避免记录引用类型
当记录对象或数组时永远记得你在记录什么。记录原始类型时使用带断点的watch表达式。如果是异步代码避免记录引用类型。
```
var arr = [{ num: 0 }];
setInterval(function(){
console.log(arr);
arr[0].num += 1;
}, 1000);
```
![careful](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/1460000016256747.png)
这里第一个属性中对象引用的值是不可靠的。当你第一次在开发者工具中显示这个属性时num的值就已经确定了。之后无论你对同一个引用重新打开多少次都不会变化。
2.尽可能使用 source map。有时生产代码不能使用source map但不管怎样你都不应该直接对生产代码进行调试。
### 异常调试
```
<script>
const age = 23;
age = 24;
console.log(age);
</script>
```
代码会报错。为了诸多原因,我们希望提前解决,所以我们希望准确知道代码在哪里有问题。也就是需要调试,希望 JS 像其他编程语言一样可以调试。
默认情况下会在 console 里面报错。如下图
![默认报错](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/2018-12-24-chrome1.png)
为了准确定位,我们可以在调试模式的右侧开启 “Pause on exception”按钮
![开启Pause on exception](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/2018-12-24-chrome2.png)
如果我们的代码加了 try.catch.,那么之前的设置是不能定位到异常的位置。
```
<script>
try {
const age = 23;
age = 24;
console.log(age);
} catch (error) {
console.log(error)
}
</script>
```
![不能定位try.catch内部的错误](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/2018-12-24-chrome3.png)
如果想捕获try.catch里面的异常则可以在调试面板的右侧勾选“Pause on caught exceptions”设置完即使是 try.catch 里面的异常也可以定位到具体位置
![打开“Pause on caught exceptions”](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/2018-12-24-chrome4.png)