https://www.html.cn/doc/chrome-devtools/settings/
https://developers.google.cn/web/tools/chrome-devtools/
Sources 面板
在代码编辑器窗格中
设置DOM断点可以用来调试复杂的JavaScript应用程序。例如,如果你的JavaScript改变了DOM元素的样式,设置一个DOM断点当元素的属性被修改时触发。在以下DOM更改都会触发断点:子树的变化,属性改变,节点删除。
在元素上右击,然后选择Break on…,再选择对于的断点类型。
只关心最后的效果是哪些样式控制的可以通过Computed查看
找到被压缩的css或者js代码点击format,就可以得到展开后的代码,并且可以进行编辑。
https://www.html.cn/doc/chrome-devtools/remote-debugging/
可以使用更专业的Android studio
当元素不在窗口中显示时,可以在元素标签上(非文本上)右击,点击Scroll into view,可使选中的元素滚动到当前窗口中。
2.如果安装了大量的游览器插件,为排除浏览器插件的事件 ,开启浏览器的隐身窗口
注意点:
条件断点分为两种情况:
在断电上右击选择Disable breakpoint(禁用断点),断点由深蓝色变为浅蓝色
设置DOM断点可以知道DOM节点或其子节点的更改,删除或添加的原因。当触发了DOM断点时,DevTools暂停页面,并带到到导致DOM变化确切的代码行。
所使用的代码如下:
<p>count:<span id="count">1span>p>
<button id="increment">Incrementbutton>
<script>
var btn = document.querySelector("#increment");
var count = document.querySelector("#count");
var i = 1;
btn.addEventListener("click", function (){
i++;
count.innerText = i;
});
script>
如果你的代码抛出异常,你不知道他们来自哪里,点击Sources(源文件)面板上的pause on exception(在异常上暂停)按钮。
DevTools在抛出异常的行自动中断。
使用命名函数而不是匿名函数来提高调用堆栈的可读性。
Sources面板中调试所用的按钮解释:
建议使用step into作为你典型的 “一次一行” 的控制执行操作,因为无论你进入和退出什么函数,它能确保一次只执行一条语句。
在怀疑未捕获异常导致问题时,使用Pause on exception(异常时暂停),但你不知道它在哪里。启用此选项时,您可以通过单击Pause On Caught Exceptions(捕获到异常时暂停)复选框来优化它;在这种情况下,只有在发生特定处理的异常时才暂停执行。
在以下代码中使用到了闭包,对象和构造函数
function funA() {
var a = 10;
return function () {
alert(a); //在此处打上断点
}
}
var b = funA();
b(); //10
<button id="btn">按钮button>
<script>
var btn = document.querySelector("#btn");
btn.addEventListener('click', function (){
sayHi();
});
function sayHi(){
var str = hi();
return 'say'+ str;
}
function hi(){
return 'hi'; //在此打上断点
}
script>
<button id="btn">按钮button>
<script>
function asyncFn(){
debugger;
}
function myClick(){
setTimeout(() => {
asyncFn();
}, 500);
}
var btn = document.querySelector("#btn");
btn.addEventListener('click', myClick);
script>
把脚本文件放入Blackbox(黑箱),可以忽略来自第三方库的调用堆栈。
当在调试时点击F11时,不想进入到某些库(如JQuery),可以将它放入到黑箱中。
<button id="btn">按钮button>
<script src="https://s3.pstatp.com/cdn/expire-1-M/jquery/3.1.1/jquery.min.js">script>
<script>
$(document).ready(function () {
function myClick() {
var arr = [1,2,3,4,5];
$.each(function (i){ //在这打上断点
console.log(i);
})
debugger;
}
$("#btn").on("click", myClick);
});
script>
3. 重复步骤1会发现,Call Stack中没有jquery,按F11也不会进入到jquery中
var a = 1;
var b = 2;
if(a === 2){ //再此打上断点
console.log('into')
}
观察和暂停执行代码有助于定位错误,并且实时编辑允许您快速预览更改,而无需重新加载。
将下面的代码放入到js文件中,并引入到html文件中
function setone(dow) {
var dow = dow - 1;
switch (dow) {
case 0:
console.log(0);
break;
case 1:
console.log(1);
break;
}
}
setone(0); //在这打上断点
使用ctrl+s暂存文件
https://www.html.cn/doc/chrome-devtools/javascript/step-code/
如果你有小的实用程序或调试脚本需要在多个页面上反复使用,请考虑将脚本另存为代码片段。您还可以使用代码片段替代书签。
https://www.html.cn/doc/chrome-devtools/javascript/snippets/
通过利用此功能,您不需要重复地将对象日志输出到控制台中。
监视a的变化
var a = 0
setInterval(() => {
a++;
}, 1000);
监视列表不是变量的实时视图,除非您逐步执行。
当你使用断点逐步执行时,监视列表中的值将自动更新。所以当变量a的值发生变化时,watch中的a的值并不会变化,需要手动刷新。
格式符 | 输出结果 |
---|---|
%s | 将值格式化为字符串。 |
%i or %d | 将值格式化为整型数字 |
%f | 将值格式化为浮点类型 |
%o | 将值格式化为一个可扩展的DOM元素。就跟在Elements (元素)面板中看到的一样。 |
%O | 将值格式化为一个可扩展的 JavaScript 对象 |
%c | 将CSS样式规则应用于通过第二个参数指定的输出字符串。 |
<div class="dom">
<ul>
<li>1li>
<li>2li>
ul>
div>
<script>
console.log("%s有%i学科,平均分为%f", 'me', 10, 90.8);
console.log('%o这是一个DOM', document.querySelector(".dom"));
console.log('%O这是一个对象', {a: 1, b:2, c:{d:4, e: 5}});
console.log("%c第二个参数中的样式将被应用到该段文字中", "color: blue; font-size: 18px; font-weight: bold;");
script>
var user = "jsmith", authenticated = false;
console.group("Authentication phase");
console.log("Authenticating user '%s'", user);
// authentication code here...
if (!authenticated) {
console.log("User '%s' not authenticated.", user)
}
console.groupEnd();
在js文件中添加如下代码
var user = "jsmith", authenticated = true, authorized = true;// Top-level group
console.group("Authenticating user '%s'", user);
if (authenticated) {
console.log("User '%s' was authenticated", user); // Start nested group
console.group("Authorizing user '%s'", user);
if (authorized) {
console.log("User '%s' was authorized.", user);
} // End nested group
console.groupEnd();
}// End top-level group
console.groupEnd();
console.log("A group-less log trace.");
当大量使用分组时,你可以将分组自动折叠起来,这可能非常有用。使用console.groupCollapsed()而非console.group()。
在js文件中添加如下代码
var user = "jsmith", authenticated = true, authorized = true;// Top-level group
console.groupCollapsed("Authenticating user '%s'", user);
if (authenticated) {
console.log("User '%s' was authenticated", user); // Start nested group
console.group("Authorizing user '%s'", user);
if (authorized) {
console.log("User '%s' was authorized.", user);
} // End nested group
console.groupEnd();
}// End top-level group
console.groupEnd();
console.log("A group-less log trace.");
console.log('这是一个条信息');
console.error('这是一个条错误信息');
console.warn('这是一个条警告信息');
console.assert()方法仅当它第一个参数求值为false时,才显示一个错误信息字符串(它的第二个参数)。
var flag = false;
console.assert(flag, 'flag为假');
在html中添加如下代码
<div class="dom">
<ul>
<li>1li>
<li>2li>
ul>
div>
<script>
// 方式一
console.dir( document.querySelector(".dom"));
// 方式二
console.log('%O', document.querySelector(".dom"));
script>
table()方法提供了一种简单的方法来查看包含类似数据的对象和数组。当调用时,它将获取到的对象属性创建为标题。每一行数据来自每个索引下的属性值。
如果没有出现图片中的效果,只需要在打开devTool(按F12打开的工具栏)的前提下,刷新页面即可。
console.table([{ a: 1, b: 2, c: 3 }, { a: "foo", b: false}]);
console.table([[1, 2, 3], [2, 3, 4]]);
function Person(firstName, lastName, age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
var family = {};
family.mother = new Person("Susan", "Doyle", 32);
family.father = new Person("John", "Doyle", 33);
family.daughter = new Person("Lily", "Doyle", 5);
family.son = new Person("Mike", "Doyle", 8);
console.table(family, ["firstName", "lastName", "age"]);
time()方法启动一个新的计时器,对于测量代码执行时间来说是非常有用的。将字符串传递给该方法,来给测量标记一个名称。
当您想停止计时器时,调用timeEnd()并传递相同的字符串传递给初始化器。
然后当timeEnd()方法触发时,控制台就会显示记录标签和执行时间。
console.time('count'); //count要与timeEnd的第一个参数保持一致
var sum = 0;
for(var i = 0; i < 1000000; i++){
sum += i;
}
console.timeEnd('count');
使用count()方法记录同一字符串输出的次数。当在同一行上给count()赋予同一字符串时,其输出的数字就加1。
function login(user) {
console.count("Login called for user " + user);
}
users = [ // by last name since we have too many Pauls.
'Irish',
'Bakaus',
'Kinlan'
];
users.forEach(function(element, index, array) {
login(element);
});
login(users[0]);
新建三个文件
html文件
<p id="demo">被替换掉的文本p>
<script src="./js/script.js">script>
<script src="./js/lib.js">script>
script.js文件
document.addEventListener('click', function (){
document.getElementById("demo").innerHTML = 'hello world';
callLibMethod();
});
lib.js文件
var callLibMethod = function callLibMethod(){
console.log('callLibMethod 被调用');
console.slog('test');
}
运行html页面,打开devtools(按F12),点击页面,在console面板中可以看到错误信息。
错误信息的意思是:发生语法错误,console.slog不是一个方法,错误是在lib.js第4行中触发的,它又是由script.js第3行中 addEventListener回调的一个匿名函数触发。
https://www.html.cn/doc/chrome-devtools/console/console-reference/
API | 描述 |
---|---|
console.assert(expression, message) | 如果expression为false,则在控制台中提示一个错误,信息为message |
console.clear() | 清空控制台。 在控制台中定义的变量依然可以使用 |
console.count(label) | 写入count()在相同的行和相同的标签已被调用的次数。 function login(name) { console.count(name + ’ logged in’); } |
console.dir(object) | 打印指定对象的JavaScript表示形式。 如果正在记录的对象是HTML元素,那么打印为DOM表示的属性, |
console.dirxml(object) | 如果可能,打印对象的后代元素的XML表示,或JavaScript表示(如果没有)。 在HTML和XML元素上调用console.dirxml()等效于调用console.log()。 |
console.error(object [, object, …]) | 打印的消息类似于console.log(),将消息样式化为错误,并包含调用该方法的堆栈跟踪。 |
console.group(object[, object, …]) | 具有可选标题的新日志记录分组的开始。 在console.group()之后和console.groupEnd()之前发生的所有控制台输出可视为一个分组。 |
console.groupEnd() | 关闭一个日志记录分组。 |
console.groupCollapsed(object[, object, …]) | 创建新的日志记录分组,初始状是折叠的而不是展开的。 |
console.info(object [, object, …]) | 打印一个消息,如console.log(),但还会在输出消息的旁边显示一个图标(带有白色“i”的蓝色圆圈)。 |
console.log(object [, object, …]) | 在控制台中显示消息。将一个或多个对象传递给这个方法。每个对象被单独计算并将其连接成一个由空格分隔的字符串。 |
console.trace(object) | 在调用该方法的地方打印堆栈跟踪。 |
console.warn(object [, object, …]) | 打印一个消息,类似于console.log(),但在输出的消息旁边还显示一个黄色警告图标。 |
注意点:
当在页面中引入jQuery时,$()就变成了jQuery的元素选择器。
通过在console面板中输入$(),1为浏览器自己的,2是引入jQuery的。
快捷方式 | 说明 |
---|---|
$() | 返回与指定的CSS选择器匹配的第一个元素。 document.querySelector()的快捷方式 |
$$() | 返回一个与指定的CSS选择器匹配的所有元素的数组。 document.querySelectorAll()的别名。 |
$x() | 返回一个与指定的 XPath 匹配的元素的数组。$x(‘html/body/div/ul/li’) |
inspect()函数将DOM元素或JavaScript引用作为参数。如果您提供的是一个DOM元素,DevTools进入Elements(元素)面板并显示该元素。如果您提供JavaScript引用,然后进入sources面板。
使用inspect方法查看DOM在element面板中的位置
html结构
<div class="box">
<ul>
<li>1li>
<li>2li>
<li>3li>
ul>
div>
在console面板中使用如下方法,浏览器会自动跳入到element面板中的元素的位置
#如果页面引入了jquery,可以使用inspect($('.box')[0]);达到同样的效果
inspect($('.box')); #这里用的是浏览器的$()
如果希望指导函数 callLibMethod在那个文件中,前提是确实有这个函数。在console面板中使用如下代码,可以跳转到callLibMethod所在文件中。
inspect(callLibMethod)
控制台存储最后五个使用的元素和对象在变量中,以方便访问。你可以使用$0 - 4,在控制台中访问这些元素。记住,计算机从0开始计数;这意味着最新的项是$0,最旧的项是$4。
$_ 属性可以获取最后一次输出的计算表达式。
方法 | 描述 |
---|---|
monitorEvents(element, event); | 第一个参数是要监听的对象。如果未提供第二个参数,所有事件都会返回。要指定要监听的事件,传递一个字符串或字符串数组作为第二个参数。 |
unmonitorEvents(element); | 停止监听element上的事件: |
在任意一个页面下,打开devtools(点击F12),在console面板下输入如下代码
#监听html的点击事件
#$('html')是浏览器获取到html元素,非jquery,具体看三章四节1小节
monitorEvents($('html'), 'click');
方法 | 猫叔 |
---|---|
getEventListeners(document); | 获取元素上绑定的事件 |
给div绑定两个click事件
<div class="box" style="height: 100px;overflow-y: scroll;background-color: #f5f5f5;;"> div>
<script src="https://s3.pstatp.com/cdn/expire-1-M/jquery/3.3.1/jquery.min.js">script>
<script>
document.querySelector(".box").addEventListener('click', function () {
console.log('box的点击事件');
});
$(".box").on('click', function () {
console.log('box的点击事件');
});
script>
在console面板中使用如下代码可以看到
#因为页面中引入了jquery,所以要使用$(".box")[0]
#如果没有引入jquery,使用$(".box")即可
getEventListeners($(".box")[0]);
使用上边的代码,可以在element面板中,选择div元素,查看在div上绑定的click事件。
Controls(控件): 使用这些选项可以控制 Network(网络)面板的外观和功能。
Filters(过滤器): 使用这些选项可以控制在请求列表中显示哪些资源。提示:按住Cmd(Mac)或Ctrl(Window / Linux),然后点击过滤器可以同时选择多个过滤器。
Overview(概览): 这个图表显示检索资源的时间轴。如果您看到多个垂直堆叠的栏,这意味着这些资源被同时检索。
Requests Table(请求列表): 此列表列出了检索的每个资源。默认情况下,此表按时间顺序排序,也就是最早的资源在顶部。单击资源名称可以获得更多信息。提示:右键单击列表的任何标题栏可以以添加或删除信息列。
Summary(概要): 概要窗格告诉您请求的总数,传输的数据量,和加载时间。
Network(网络)面板会高亮显示两个事件:DOMContentLoaded和load。
Time To First Byte
(接收到第一个字节所花费的时间)。这个时间除了等待服务器传递响应所花费的时间之外,还捕获到服务器发送数据的延迟时间。https://www.html.cn/doc/chrome-devtools/memory-problems/
内存问题很重要,因为它们经常被用户感知。用户可以通过以下方式感知内存问题: