前段时间开发PC后台页面时,在查询资料无意间打开一个网站时,无意间(开发者工具开着)看一个很一个很骚气的console输出(很大红色字号 I ❤ XXX,还是之前见的少),当时觉得很好玩,只是当时PM催着做需求,没有时间去做过多研究。趁着五一假期期间又重看了遍console,发现了好些很有用的方法只是之前不知道😂。
先来统揽一下console的方法:
interface Console {
assert(condition?: boolean, message?: string, ...data: any[]): void;
clear(): void;
count(label?: string): void;
debug(message?: any, ...optionalParams: any[]): void;
dir(value?: any, ...optionalParams: any[]): void;
dirxml(value: any): void;
error(message?: any, ...optionalParams: any[]): void;
exception(message?: string, ...optionalParams: any[]): void;
group(groupTitle?: string, ...optionalParams: any[]): void;
groupCollapsed(groupTitle?: string, ...optionalParams: any[]): void;
groupEnd(): void;
info(message?: any, ...optionalParams: any[]): void;
log(message?: any, ...optionalParams: any[]): void;
markTimeline(label?: string): void;
profile(reportName?: string): void;
profileEnd(): void;
table(...tabularData: any[]): void;
time(label?: string): void;
timeEnd(label?: string): void;
timeStamp(label?: string): void;
timeline(label?: string): void;
timelineEnd(label?: string): void;
trace(message?: any, ...optionalParams: any[]): void;
warn(message?: any, ...optionalParams: any[]): void;
}
基础方法
日常用到比较多的log()
、info``()
、debug()
、warn``()
、error``()
,分别用于 日志、信息、调试、警告、错误 日志的输出,这里我把他们叫基础方法。其中info()
、debug()
只是log()
的别名,三者输出的实际效果是一样的,warn()
和error()
的输出会在浏览器窗口会展示不同的黄色、红色的警告颜色,点击的话可以跳转到代码行。
在实际日常使用中,只用console输出文本到控制台是不够的,我们还需要其他更丰富的输出。
打印对象
在开发中,我们时长需要查看某个、某些对象的结构,这时就需要把这个对象打印出来:
var aObject = { id: 1, name: "张三" }
//打印单个对象
console.log('aObject = ',aObject )
var otherObject = { id: 2, name: "lisi"}
//打印多个对象
console.log('aObject = ',aObject,'otherObject = ',otherObject)
格式化式输出
console还提供了方便字符串格式化输出(其他语言上一般这样叫,js中叫字符串替换),它允许你用特定的字符串来占位,在后面参数中把占位的替换掉。
console.log("这个一个%s输出示例,eg. muber = %d", "格式化",12.34);
//输出结果:这个一个格式化输出示例,eg. muber = 12
可以看到实现的很优雅,比通过字符串拼接或${}
的方式来取值在拼接展示更直观。目前支持一下字符串
格式化字符串 | 描述 |
---|---|
%o or %O |
打印 JavaScript 对象。在审阅器点击对象名字可展开更多对象的信息。 |
%d or %i |
打印整数。支持数字格式化,小数点后的会省略。 |
%s |
打印字符串。 |
%f |
打印浮点数。 |
注:在处理数字时有些浏览器上支持类似
%2d
、%.2f
这样的表示支持整数的位数(不足的往前补0)、小数点后的位数(不足的往后补0)
个性化样式
有的网站我们打开时会在开发者工具console里看到很多更新话的输出,像这样:
或者像这样
乍一看很是高端,实际上往大的范畴看也是属于上面说的《格式化式输出》的一种,要想实现上面的效果,可以使用 %c
为打印内容定义css样式
console.log('%cI %c❤ %cChina',
'color:pink;font-size:50px;font-weight:500',
'color:#ff5555;font-size:70px;font-weight:500',
'color:white;font-size:50px;font-weight:500;background:red;');
其中支持的css样式属性有background
、border
、border-radius
、box-decoration-break
、box-shadow
、clear
、float
、color
、cursor
、display
、font
、line-height
、margin
、outline
、padding
、text-transform 这类 text-* 属性
、white-space
、word-spacing
、word-break
、writing-mode
。
到这里console的基础方法的使用基本上了解的差不多了,接着我们继续看console中和console.log()类似的。
输出可浏览的对象
console.dir()输出的是可浏览的对象(类JSON格式的),而log()输出的是目标的.toString()实现(各浏览器实现可能不一致)。通过下面的例子可以明显的看出二者的区别(chrome中):
var functor=function(){
//test
}
functor.prop=1;
还有一种实现可以看出二者的区别:
注:在有的浏览器中(eg.火狐),二者实现是一致的。console.dirxml()实际调用的就是console.log(),输出可浏览对象的话展示的是类XML风格的。
分组输出
在开发阶段如何更直观的查看某些特定场景日志的输出呢,当然是对它进行分组展示了。console中对此也提供了支持,那就是console.group()、console.groupEnd(),先看实际效果:
实现代码如下(group
和groupEnd
要成对出现),
console.log("--------group start--------");
console.group('A');
console.log("-1-1-");
console.group('B');
console.log("-2-1-");
console.group('C`');
console.log("-3-1-");
console.log("-3-2-");
console.groupEnd('C`');
console.groupCollapsed('C``');
console.log("-3`-1-");
console.log("-3`-2-");
console.groupEnd('C``');
console.groupEnd('B');
console.log("-1-2-");
console.groupEnd('A');
console.log("--------group end--------");
可能存在某些组的数据比较多,希望默认是折叠状态,可以使用console.groupCollapsed()
来实现。
表格输出
当你要输出的是一个数组对象时(更严谨的说是tabularData),你可以使用 console.table() 打印一个非常漂亮可视化表格,谁用谁知道。
var tab=[{"name":"张三","age":31,"tel":"13800000001"},{"name":"李四","age":32,"tel":"13800000002"},{"name":"王五","age":33,"tel":"13800000003"},{"name":"赵六","age":34,"tel":"13800000004"}];
console.table(tab)
时长统计
之前想知道某个方法、或某个阻塞式步骤执行时长,通常是在开始时计下时间戳,结束时计下时间戳,二者的差值就是执行的耗时,这样做挺好的,作为一个看起来像高级些的程序员,代码能精简就精简些(主要是懒),console.time()就把我们刚做的事都做好了。
console.time("time-tag");//开始计时,参数需要保证唯一性(后面打印时间、结束需要用到)
alert("alert-1");
console.timeLog("time-tag");//获取一下从开始到现在的时间
alert("alert-2");
console.timeEnd("time-tag");//结束计时,同时会打印时间
注:一个页面最多同时只能有 10000 个计数器运行,Performance中也能展示这个时间(如下图)。
计数
如果想要快速统计某个方法或步骤执行的次数,console.count()你一定喜欢,它只需要用一行代码就能统计执行的次数(不过有个确定,就是每一次执行都会答应一条日志,如果执行数量特别多话,控制台不忍直视)。
for (let i = 0; i < 20; i++) console.count("some-tag");//参数需要保证唯一性,相同的会累加计时的
如果想要重置计数,可以使用console.countReset()
。
日志断言
如果只想在某些结果和自己预期不一致时的打印日志来跟踪问题(可以规避使用if),这种情况推荐使用console.assert()
,当判断第一个参数是否为假时(not truthy),抛出异常并且在控制台输出相应信息。
console.assert(Date.now()%2==0,'condition is not truthy');
//输出报错信息:Assertion failed: condition is not truthy
调用堆栈
一些共用的方法,调用的地方有N多个,当出问题时,我们并不能很直观的看到是因为哪个调用的地方使用的不规范导致了异常,这时就需要用到了console.trace()
来展示调用的堆栈,帮助我们快速的定位调用的入口。
function foo() {
function bar() {
console.trace();
}
bar();
}
foo();
//输出:
//VM2494:3 111
//bar @ VM2494:3
//foo @ VM2494:5
//(anonymous) @ VM2494:8
性能分析
在调试性能时,console提供了profile()的方法来帮助我们查看CPU的使用情况。
let arr = new Array(1000000);
var submit = document.getElementById('submit');
submit.onclick = function runMethod() {
console.profile("fotime");
fun1();
console.profileEnd("fotime");
}
function fun1() {
for (let i in arr) {}
fun2();
}
function fun2() {
arr.forEach(it=>{});
}
代码执行后,可以通过控制台JavaScript Profiler看到方法的耗时。
展示样式有三种(chart
、Heavy
、Tree
),可以根据自己的偏好/场景来查看。其中的Self Time 标识的是方法自身的执行时长,不包括调用其他方法的时间,想要包含的话可以使用Total Time。
事件标签
console.timeStamp()
需要配合着Performance使用,其作用是在时间轴面板上添加一些你想要事件标签。
let arr = new Array(1000000);
var submit = document.getElementById('submit');
submit.onclick = function runMethod() {
console.timeStamp("开始执行")
fun1();
console.timeStamp("执行结束")
}
function fun1() {
console.timeStamp('fun1开始执行结束')
for (let i in arr) {}
fun2();
}
function fun2() {
console.timeStamp('fun2开始执行结束')
arr.forEach(it => {});
}
其他方法
console.clear()
:当输出的目标是tty时,会清空当前的终端面板;~~console.exception()~~
:已过时,console.``error()
方法的别称;~~console~~``~~.~~``~~markTimeline()~~
:已过时,推荐使用console.timeStamp()
;~~console~~``~~.~~``~~timeline~~``~~()~~
:已过时,推荐使用console.time()
;~~console~~``~~.~~``~~timelineEnd~~``~~()~~
:已过时,推荐使用console.timeEnd()
;
//todo