一些DevTools的小技巧-让你不止会console.log()

原创
03/25 13:51
阅读数 7.2K

转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。

原文参考:https://www.sitepoint.com/beyond-console-log-level-up-your-debugging-skills/

在开发过程中,你可能会经常用到控制台命令console.log(),但是,其实除了这个命令外,还有一些其他的命令和技巧可供我们使用,让我们看看它们究竟是什么,会不会为你的调试能力带来一点新的启发。

突破舒适区

同样作为开发者,有一点不可否认的是程序员这个群体总是会不断优化工作流程,使其变得更高效。不过这很容易使我们陷入误区,让我们很难突破已经惯有的工作流程,继而闭耳塞听得认为没有比现在更好的工作方法和流程。

一般Web开发者的工作流程是在IDE中写好代码并保存,然后到浏览器中刷新测试。同时使用浏览器的DevTools调整CSS,还可以测试产品在不同分辨率和移动设备上的表现。在需要深入研究的地方可以通过添加 console.log()语句来调试我们的脚本。

如果console.log()在最终产品中被滥用,那么你在网上冲浪时如果一直打开DevTools,你就会在控制台中看到很多本不该出现在最终产品中的调试信息。

下面让我为大家介绍一下除了console.log()之外的其他命令,看看它们会不会为各位的工作带来什么新的启发吧!

控制台的多种用法

我们可能已经习惯了通过 console.log("参数") 来了解程序中正在发生的事情,一般来说对于字符或数字这种类型的输出,这种用法就足够了,不过在输出些类似像对象、数组类型的数据时却没有那么顺手。

第一个技巧是在变量上加上大括号,这样不仅可以打印出它们的值,还可以打印出变量的名称,这使我们在日志中更方便的定位到什么值来自哪里。

1
2
3
let   x = 2;
console.log(x)  //   2
console.log({x})  //   {x: 2}

  

格式化日志

你可以在console.log中使用以百分号操作符指代不同格式的记录值来格式化字符串,以下是操作符类型的定义:

  • %s: 字符串
  • %i或%d:整数。
  • %f:浮点数。
  • %c:CSS样式。
  • %o:可扩展DOM元素。
  • %O:可扩展JavaScript对象。

你可以把它们分别放在控制台试试效果,首先是字符串和整数的示例:

1
2
console.log( '%ix %s developer' , 10,  'console' );
//   10x console developer

  

如果计划将数字格式化为整型,可以使用如下示例:

1
2
console.log( '%i' , 12.34455241234324234);
//   12

%c操作符可以令你使用CSS样式定制输出日志的样式

1
console.log( '%cPay attention to me' , 'color:firebrick;font-size:40px' )

其他更多日志功能可以查看官方文档,看看有哪些已经实现了,避免重复造轮子。

分组日志

你可以使用console.group()来对日志进行分组,以将其显示为可扩展和可折叠的组。

1
2
3
4
5
6
7
const label =  'The Millenium Falcon Crew' ;
console.group(label);
console.log( 'Leia' );
console.log( 'Han' );
console.log( 'Chewie' );
console.log( 'Ben' );
console.groupEnd(label);

 

 

你可以嵌套分组,并可以使用 console.groupCollapsed() 在默认情况下不展开它们:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const extendedlabel =  'The Millenium Falcon Crew extended' ;
const meat =  'Humanoids' ;
const metal =  'Droids' ;
console.group(extendedlabel);
console.groupCollapsed(meat);
console.log( 'Leia' );
console.log( 'Han' );
console.log( 'Chewie' );
console.log( 'Ben' );
console.groupEnd(meat);
console.group(metal);
console.log( 'R2D2' );
console.log( 'C3PO' );
console.groupEnd(metal);
console.groupEnd(extendedlabel);

  

日志控制台过滤

除了console.log外,你也可以使用 console.info()、console.error()和 console.warning()来代替它。通过这些语句,你可以在控制台侧边栏或下拉列表中来过滤你在控制台中看到的消息。这样一来,你可以更容易地在来自第三方脚本和项目中的其他脚本中找到自己的日志消息。

其他控制台命令

你可能在debug时曾创建过统计某个方法被调用或被执行次数的变量。这里推荐另一种方法, console.count()和 console.countReset(),通过它们你可以创建任意数量的变量,并通过标签来区分。

1
2
3
4
5
6
7
console.count( 'Chocula' );  //   Chocula: 1
console.count();  //   default: 1
console.count( 'Chocula' );  //   Chocula: 2
console.countReset( 'Chocula' );
console.count();  //   default: 2
console.count();  //   default: 3
console.count( 'Chocula' );  //   Chocula: 1

您还可以使用console.time()方法去统计代码执行的总耗时:

1
2
3
4
5
console. time ( 'go' );
for ( let   i = 0; i < 200000; i+=1) {
   let   x = Math.random()*2000;
}
console.timeEnd( 'go' );  //   go: 11.7861328125 ms

使用 console.dir()不仅可以显示内容,还可以显示你发送的数据类型。例如,如果你想要一个节点的XML表示,你可以使用console.dirxml()。而console.table()对于显示JSON数据作为一个可排序的表格显示效果也很好。

使用实时表达式Live Expression替代console.log

使用 console.log() 来监测那些变化范围很大的数值时,不仅低效且困难。你可在在开发人员工具中通过点击“眼睛“图标来激活Live Expression功能。它可以将你想要关注的数值pin在工具顶端。

 

 

例如,你可以先输入document.activeElement 来试试。该表达式表示当前获得焦点的元素。

在这有一点需要说明,因为Live Expression并不和某一个站点及域名所关联,所以它会一直保留在你的DevTools中。因此建议在完成一项调试后及时删除它们,以免为调试其他站点时带来不必要的麻烦。

使用控制台处理当前文档

开发人员工具中的控制台不仅仅是用于显示日志的一种方式。它是一个REPL,可让您编写和执行JavaScript并使用自动完成功能了解当前文档的可用方法和属性。

你可以试试,在开发人员工具的控制台,输入doc并按下tab,它会自动将其转为document。如果输入’.’ 你会看到所有document可用的方法和属性。这是一种学习可用方法和属性的有趣且简单的方法之一,这样可以使你在短时间内写出大量代码。

  

除此之外,控制台和当前文档进行交互还有很多快捷方式可供你使用 “控制台实用程序”。其中一些是:

  • $_存储最后一条控制台命令的结果。所以如果你之前输入了2+2并按回车键,你在输入$_将为你直接提供4。
  • $0 到 $4 是你通过Elements 选项卡选中元素的堆栈,$0 为当前你选择的元素。
  • $() 通过选择器选择页面中的元素
  • $$()返回与给定选择器匹配的元素数组。此命令等同于document.querySelectorAll()。。
  • $x() 允许您通过XPATH选择DOM元素。
  • copy() 将您提供的所有内容复制到剪贴板。
  • clear() 清除控制台。
  • getEventListeners(node) 返回在指定对象上注册的事件监听器。
  • monitorEvents(node, events) 监视并记录对象上发生的事件。
  • monitor(method) 每当调用方法时,都会创建一个日志。

其中有些方法的功能很强大,但可能我们在并不清楚的前提下自己实现了一系列 console.log() 语句。

例如如下使用场景:

1
2
monitorEvents(window, [ 'resize' ,  'scroll' ]);
monitorEvents($0,  'key' );

每次窗口滚动或调整大小时都会记录一条日志。第二个示例比较有意思,因为它记录了当前选定元素上的任何按键行为。

以下代码列出页面中的所有a标签(因为$$('a')是document.querySelectorAll('a')的简称),并以可排序的表格形式显示。作为table方法的第二个参数的数组定义了表格的列。否则,链接的每个属性都会变成一列,那就很难浏览了。这个表不仅是可排序的,而且你还可以复制和粘贴它--例如,复制到Excel中。

1
console.table($$( 'a' ),[ 'href' , 'text' ])

  

与其使用复杂的JavaScript来过滤这些结果,你不如试试CSS选择器。再比如,你想获得一个文档中所有非内嵌图片的src和alt信息的表格,你可以使用以下方法:

1
console.table($$( 'img:not([src^=data])' ), [ 'src' , 'alt' ])

另外,当您使用Markdown生成HTML时,大多数页面生成器都会在标题上创建自动ID,例如 # New Stuff标题会变成<h1 id="new-stuff">New stuff</h1>。如果我需要批量创建许多指向这些锚点的URL,但不想手动去做这些事时,可能需要通过控制台编写脚本来为我做这件事:

1
2
3
4
5
6
7
8
9
let   out =  '' ;
$$( '#main [id]' ).filter(
     elm => { return   elm.nodeName.startsWith( 'H' )}
).forEach(elm => {
    out += `${elm.innerText}
${document.location.href} #${elm.id}
`
});
copy(out);

结果是一个文本块,每个标题的文本内容后跟指向该标题的完整URL。

这里展示了$$快捷方式的一个有趣的额外功能。document.querySelectorAll('#main [id]').filter() 会导致一个错误,因为返回的值不是一个数组而是一个NodeList。你需要用[...document.querySelectoAll('#main [id]').filter()]或Array.from(document.querySelectoAll('#main [id]').filter())方法把它强制转换成一个Array,这在相当长的一段时间中困扰着从jQuery转到JavaScript的开发者,而使用$$,可以直接使用所有的Array方法。

一般来说,你可以通过控制台来改变浏览器页面中的所有元素。而且你还有一个额外的好处,就是可以使用DevTools的元素选项卡来获得元素所有的页面路径。点击每个元素旁的...菜单,并通过弹出的上下文菜单中选择你要复制的路径。  

  

虽然控制台本身很好用,但很快你就会发现Console在编写代码存在着诸多困难,例如,Console是单行环境,不小心点击Enter后就会立即执行。不过在这最后为大家介绍一个小技巧,你可以使用Shift + Enter来代替编写多行脚本。

Sources

总的来说,Console是一个很好的测试环境,但对于编辑体验来说却很差。不过还好在Sources面板中也有一个完整的编辑器。在那里,你可以检查当前页面的代码,并编写更复杂的脚本与之交互。

除了点按上面tab菜单之外,DevTools还有一套快捷键Command Menu供你使用,你可以通过按control + shift + P(Windows, Linux)或Command+Shift+P(macOS)来访问它。或选择(...)菜单,选择“Run command”。

Snippets 代码片段

Snippets是保存你曾写过的能明显提高开发效率的代码小片段。在DevTools中点击Command Menu键盘快捷键,输入snip并按下Enter键,选择创建一个新的snippet,这样就会进入Snippets编辑器,具体如下图所示:  

  

右边的窗体包括一个完整的源码编辑器,具有关键词着色、自动补全、多光标等功能。下面我们开始试试上面的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
console. clear ();
let   out =  '' ;
let   problems = [];
$$( 'a' ).forEach(a => {
   let   text = a.innerText.trim();
   let   prefix =  '' ;
   if   (!text) {
     if   (a.querySelector( 'img' )){
       text = a.querySelector( 'img' ).alt;
       prefix =  'Image: ' ;
     }
     if   (a.getAttribute( 'aria-label' )) {
       text = a.getAttribute( 'aria-label' );
       prefix =  'Aria Label: ' ;
     }       
     if   (a.getAttribute( 'aria-labelledby' )) {
       text = $( '#'   + a.getAttribute( 'aria-labelledby' )).innerText;
       prefix =  'Aria Labelled By: ' ;
     }       
   }
   if   (text) {
     text = prefix + text
   }  else   {
     a.style.border =  '1px solid firebrick' ;
     problems.push(a);
   }
   out += `
${text|| 'No Link text' }
${a.href}`;
});
if   (out ===  '' ) {
   console.warn( 'Sorry, no links found' );
}  else   {
   copy(out);
   console.info( 'done harvesting links, ready to paste' );
   if   (problems.length > 0) {
     console.warn( 'There were %d issues:' , problems.length);
     console.groupCollapsed( 'Links without text' );
     problems.forEach(a => {console.dirxml(a)});
     console.groupEnd( 'Links without text' );
   }
}

以下是执行演示:

  

Overrides

Override是通过修改远程文件的本地副本,实现本地测试替换服务器文件。例如,你可以在本地编辑完整的复杂样式表,但无需等待冗长的重新build和部署过程即可看到效果,这也是能在开发阶段即可发现问题的一种快捷的方式。

将开发人员工具和VS Code集成

你可以通过安装Microsoft Edge Tools for VS Code扩展 ,即可在编辑中获得开发人员工具,通过下图可以看到基础用法。

最后总结

希望通过这篇文章,可以使你能更全面的对DevTools有一些了解,而不仅仅只会使用console.log。另外作为一个开发人员除了上述的这些技巧外,还应多多习惯使用断点及条件断点进行调试,希望能够通过更多的使用和练习来达到熟练的状态。

展开阅读全文
打赏
3
7 收藏
分享
加载中
打赏
0 评论
7 收藏
3
分享
返回顶部
顶部