控制台有两个主要用途: 查看日志和运行JavaScript。
查看日志
平时在开发过程中,我们总是借助console来辅助调试,那么console是个什么东西呢?我们可以在Console面板打印下看看。
可以看到
console对象上有很多方法,总的来说可以分为两大类,日志和非日志。
日志
DevTools给console中的打印日志的方法定义了四个级别,分别是Verbose、Info、Warning
和Error。如下表格所示:
| 级别 | 方法 |
|---|---|
Verbose | debug |
Info | log、info、count、countReset、dir、dirxml、table、time、timeEnd、trace |
Warning | warn |
Error | error、assert |
在控制台我们也可以通过日志级别来过滤日志,如下图所示:
下面来看下这些方法的使用:
Info
①、log和info
日常开发中使用最多的就是log了,info与它等价。如果有需要的话,也可以设置输出日志的样式,比如console.log('%c hello word', 'color: red; font-size: 30px')。如下图所示:
如果想要输出的日志带上时间,可以
shift+ctrl+ p调出命令行,在上面的输入框中输入show time,然后选中show timestamps即可。
用log输出对象的时候需要注意一个小细节,参考如下demo:
obj的值是在第五行修改的,但是在第四行的时候打印出的obj的值,已经是修改后的值了,这是因为当我们手动展开该变量的时候,控制台才获取该变量的值。如果想要在第四行准确输出obj的值,可以使用console.log(JSON.stringify(obj))输出。
②、count和countReset
count和countReset是配套使用的,用于计数和重置计数。举个例子,在下面的demo中定义了一个add方法,然后add在不同的情况下被调用,那么可以用count来计算add一共调用了多少次。
function add(a, b) {
console.count('call add') // count的入参可以是自定的标签名,缺省是default
return a + b
}
add(1,2)
add(1,3)
console.countReset('call add')
add(1,4)
该demo的运行结果如下:
call add: 1
call add: 2
call add: 1 # 因为countReset将计数器重置了,所以又从1开始了
③、dir与dirxml
dir用于打印一个对象的属性和方法,而dirxml则用于打印DOM节点。如下图所示:
ps:dir与dirxml都是非标准特性。
④、table
table用于打印一个数组中的数据,如下图所示:
如果只需要显示一列或者某几列,可以使用第二个可选参数来指定需要展示的列,如下图所示:
⑤、time、timeEnd和timeLog
time用于启动一个计时器;timeEnd用于停止计时器;timeLog则用于在这个计时器期间打印其他的带计时功能的日志。这三个方法是搭配使用的。举个例子,运行如下的代码:
let sum = 0;
console.time('count')
for (let i = 0; i < 10000; i++) {
if (i % 1000 === 0){
console.timeLog('count', `在${i}处花费的时间`)
}
sum += i
}
console.timeEnd('count')
运行结果如下所示:
和count一样,这三个方法都可以传入一个字符串用于标记该计时器,比如上面例子中的count,如果不传的话,默认是default。
⑥、trace
trace用于打印堆栈信息,举个例子:
const first = () => {
second()
};
const second = () => {
third()
};
const third = () => {
console.trace()
};
first();
执行上面的代码,可以看到当前的调用栈信息:
Verbose
debug
和info一样,debug和log也是等价的,唯一的区别是debug的级别属于verbose,所以在默认情况下,在控制台用console.debug输出一个信息,默认是看不到这个输出信息的,需要调整日志的过滤级别,如下图所示:
Error和Warn
warn和error就不细说了,平时开发中见过太多了💔,希望大家在以后的开发过程中无error,无warn🙏
捎带提一下assert,它属于Error级别,如果断言是true,则控制台无输出,如果断言是false,那么控制台会输出一个error级别的信息,如下图所示:
非日志
①、clear
clear用于清除控制台的输出,和下图中左上角的清除图标一样的效果,两者的区别是:当Console面板的Setting中勾选了Preserve log的时候,clear方法是失效的,清除不了控制台的输出;但是点击清除的图标则是可以清除成功的,如下图所示:
②、group、groupEnd和groupCollapsed
这三个方法都是用于对输出的信息进行分组,如下图所示:
group和groupCollapsed的区别在于:初始情况下,groupCollapsed是将信息折叠起来的,需要手动点击展开。
③、context
在控制台打印console.context(),可以看到如下图所示:
乍一看,和
console相等,其实它的返回值就是console的子集,缺少了memory属性和context方法。
④、memory
memory是一个属性,可以查看当前的内存信息,如下图所示:
jsHeapSizeLimit:上下文内可用堆的最大体积,单位是字节。
totalJSHeapSize: 已分配的堆体积,单位是字节。
usedJSHeapSize: 已使用的堆内存,单位是字节。
三者之间的关系是:jsHeapSizeLimit >= totalJSHeapSize >= usedJSHeapSize
ps: jsHeapSizeLimit应该是操作系统根据机器的内存大小分配给浏览器中的JS对象可以使用的最大空间,小样本范围测试了下,jsHeapSizeLimit的大小和操作系统、浏览器均无关系,只和机器的内存有关。16G的机器的jsHeapSizeLimit是3.5G左右,而8G的机器分配的jsHeapSizeLimit是2G左右。
⑤、profile和profileEnd
profile和profileEnd是用于性能分析的,运行下面的代码:
let arr = new Array(100000).fill(1)
function A () {
for (let i = 0; i < arr.length; i++) {}
}
function B () {
for (let i = 0; i < arr.length; i++) {}
C();
}
function C () {
for (let i = 0; i < arr.length; i++) {}
}
function fun () {
console.profile('loop');
A();
B();
console.profileEnd('loop');
}
fun();
在控制台可以看到如下输出:
在
JavaScript Profile面板中可以找到该性能报告:
在上面的性能报告中,可以看到函数调用栈和每个函数的执行时间。
Self Time:表示当前函数自身运行耗时,不包括当前函数中调用的其他函数运行耗时。
Total Time:表示当前函数运行总耗时,包括了自身运行耗时+函数内部调用的其他函数的运行耗时。
ps: 不是标准特性,不要在生产环境使用。而且在上面的demo中,如果数组的长度不够的话,性能报告里面是看不到该方法的执行时间的。
⑥、timeStamp
timeStamp用于向Performance面板添加一个标记来进行调试,放到以后的Performance面板来讲解。
ps:这是一个非标准特性,不要在生产环境使用。
运行JavaScript
控制台是一个REPL,比如你在控制台输入2 + 5,回车之后马上就可以得到结果7。
ps:REPL: Read(读取)-Eval(执行)-Print(输出)-Loop(循环),一般翻译成:交互式解释器
控制台设置
Hide network
不勾选Hide network的时候,如果网络请求有错误的时候,是会在控制台输出错误日志的,如果勾选了该选项,将会隐藏这些错误信息,如下:
Preserve log
默认情况下,每次刷新页面的时候,console下的输出都会被清除,如果想要不清除之前的输出,可以启用Preserve log,如下:
Selected context only
和顶部的上下文选择配合使用,用于筛选日志。
Group similar message in console
将相同的日志分组,如下所示:
Log XMLHttpRequests
勾选了Log XMLHttpRequests,可以看到所有xhr请求的日志,点开其中某个xhr的日志,还可以看到完整的调用栈。如下图所示:
ps: 还记得之前的Hide network吗?如果这两个选项同时开启会怎么样?
Eager evaluation
提早评估,如下:
Autocomplete from history
根据日志自动补全,如下图所示:
上图中蓝色箭头开头的,也就是框出来的部分就是之前输入的历史记录。
Evaluate triggers user activate
有些js api无法通过代码直接调用,比如window.open(),需要开启该选项才能调用。
使用介绍
选择执行上下文
如下图所示,点击top右侧的下拉箭头可以选择当前console所在的执行环境,默认是top,表示的是页面的顶部框架。比如在paasdev.kdcloud.com中top指的是控制台。而控制台中的每个服务的图表是以iframe的形式嵌套进来的,点击下拉框的箭头可以选择切换当前console的执行环境。
在控制台和容器的
index.html上有后端设置的模板变量PUBLIC,PUBLIC是全局变量,直接挂载在window上,比如控制台的window上的PUBLIC我们可以通过如下方式查看:
那容器上的
PUBLIC在console面板下怎么查看呢?可以通过切换执行上下文来查看,如下图所示:
创建实时表达式
如下图所示,点击眼睛图标可以创建一个表达式,实时监测表达式的值。
举个例子,创建了一个实时表达式
document.body.clientWidth,当修改窗口的大小的时候,如下图所示,该表达式的值在实时变化。
ps: 执行频率是250毫秒。
日志过滤
根据执行上下文过滤
先点击top选择要显示日志的执行上下文,然后在console settings中勾选Selected context only即可。
按照日志级别过滤
如下图所示:
点击侧边栏也可以根据日志级别进行过滤:
需要注意的是,当打开了侧边栏的时候,顶部的过滤下拉框是置灰的。如果只想查看来自本网页的消息,可以点击user messages。
根据关键字或者正则过滤
如下图所示:
根据url过滤
在输入框中输入要url:目标url即可,如下所示:
如果是不需要显示某个
url的消息,则输入-url:目标url。
隐藏的常量和方法
$_
返回最近的表达式的值
$0-$4
返回最后五个在Element中选中的DOM元素或者是在Memory面板中选中的JS堆栈对象。$0表示最近的一个,以此类推。
$(selector[, startNode])
该函数等价于document.querySelector(),startNode的默认值是document,指定查找的范围。
$$(selector[,startNode])
该函数等价于document.querySelectorAll()。
$x(path[, startNode])
返回满足path的DOM元素数组
copy(object)
使用copy(obj)可以将对象复制到粘贴板。
const data = [{
name: 'hello',
age: 10
}, {
name: 'world',
age: 20
}]
copy(data)
debug(function) 和 undebug(function)
当你想要给某个函数打断点的时候,可以使用debug(function),当该函数调用的时候,将暂停在函数体的第一行,例子如下:
function add(a, b) {
return result
}
debug(add)
add()
其实上面的代码也就等价于:
function add(a, b) {
debugger
return result
}
add()
undebug(function)用于取消函数断点
getEventListeners(object)
返回参数object上注册的事件,如下图所示:
也可以通过
ctrl+shift+p调出命令行,输入show Event Listeners查看选中的元素上绑定的事件,如下图所示:
勾选
Ancestors可以查看该元素继承来自父组件的事件。点击事件右侧的Remove可以移除该事件。
monitor(function)和unmonitor(function)
monitor用于监听函数,unmonitor用于取消函数监听,如下图所示:
monitorEvents(object[, event])和unmonitorEvents(object[, event])
monitorEvents用于监听object上的单个事件、多个事件或者事件类型。unmonitorEvents用于取消object上的事件监听。
# 监听单个事件
monitorEvents(document.querySelector('a'), 'click')
# 监听多个事件
monitorEvents(document.querySelector('a'), ['click', 'mousemove'])
# 监听一种事件类型
monitorEvents(document.querySelector('a'), 'mouse')
其中入参的事件名称和事件类型如下图所示:
举个例子:
其他
有时候开发过程中我们需要临时测试一下第三方包的功能,比如想用下moment,这种情况下我们可以直接在console中测试,只需要安装一个插件Console Importer:
通过
$i(包名)加载进来就可以使用了: