让强大的console家族助你一臂之力

此为转载文章,原文链接在底部~

我们在控制台打印一下console,看看它还有哪些神奇的方法:


console.png

下面我们从最简单的console.log方法开始,逐个分析其他方法以及所涉及到的调试技巧。

一、console.log()打印内容。

此处:主要聊一聊console.log()的占位符。其共有五种占位符

  • %s 字符串
  • %d 或 %i 整数
  • %f 浮点数
  • %o 对象的链接
  • %c CSS格式字符串
    如果方法的第一个参数中使用了占位符,那么就依次使用后面的参数进行替换。
const name = 'chinaBerg';
const age = 88;
const money = 12.88;
const obj = {
    status: '很积极'
}

console.log('我叫%s,%d岁,有%f元,状态:%o', name, age, money, obj.status, '又打印一句话')
谷歌打印结果.png

可以看到我们后面使用的参数对前面的占位符进行了替换,有点像我们字符串拼接的简化操作。比如我们es5中的字符串拼接:

console.log('我叫' +  name + ' ,' + age +'岁,有' + money + '元')

es6已经有了更强悍的字符串模板:

console.log(`我叫${name},${age}岁, 有${money}元`);

es6的字符串模板中,只能使用%c占位符,其他占位符是没有效果的。

// 注意这里字符串模板的最后插入了%f
console.log(`我叫${name},${age}岁, 有%f元`, 12.88);
%f没有效果.png

%c占位符还是略有趣味的:

const css1 = 'font-size: 22px;font-weight: bold';
const css2 = 'border: 1px solid green';
const css3 = 'color: #fff;background: #f00';

// 占位符填入                
console.log('%c %s + %s = %s', css1, 1, 2, 3);
// 字符串拼接形式中插入%c占位符
console.log('%c我的名字叫' + name + ', 今年' + age + '岁', css2);
// es6字符串模板中插入%c占位符
console.log(`%c我叫${name},${age}岁, 有%f元`, css3);
谷歌打印效果.png

可以看到这些打印的内容已经被添加了我们的样式。

二、console.info()和console.debug()

console.log()很像的还有俩,一个是console.info(),一个是console.debug()。其实这个三个功能都是一样的,只不过有些区别,下面就具体介绍一下这三个方法。

console.log('我是console.log()打印出来的');
console.info('我是console.info()打印出来的');
console.debug('console.debug()打印出来的')
谷歌浏览器.png

火狐.png

ie.png
  • console.log()方法,无论哪个浏览器,打印出的效果都是一样的。
  • console.info()方法,ie没有打印出来,即不支持这个属性。但是在谷歌和火狐上又略有区别:打印的结果是一样的,但是火狐控制台上,会在打印的结果前面添加一个类似i的小符号。
  • console.debug()方法,谷歌和opera是不支持的,ie和火狐是支持的。
    所以呢,既然三个方法功能是基本一样的,我们如果只想打印一些内容的话,还是老老实实的使用console.log()稳一点。当然了,这也抵不住你就使用火狐来debug呢!可是,考虑到如果你的代码库的某些打印信息需要给别的开发者看的话,还是用兼容性更好的稳一些。

补充修正:chrome并不是不支持console.debug,只是默认日志级别不打印调试信息,把verbose勾上就好了

三、console.clear()

清除控制台打印的内容,并将光标回归到第一行


image.png

和我们点击控制台的这个清除按钮的效果一样

四、console.assert(表达式 [,arg1, arg2……argn])打印断言

第一个参数是用来判断是否打印断言的表达式,只有当表达式的值为false的时候,才会打印后续的参数:

const arr = [1, 2, 3];

// 打印断言,如果arr[0]的值不等于2,则打印提示信息
console.assert(arr[0] === 2, 'arr[0]的值不等于2');
谷歌控制台.png

没有参数,打印字符串.png
  • 客户端的console.assert()打印断言,并不会阻塞后续代码的执行,只是在断言的表达式为false的时候,向控制台打印你的内容。
  • 而在node.js中,值为假的断言将会导致一个AssertionError被抛出,使得代码执行被打断。这两者是有区别的。

五、console.count() 打印计数

输出他被调用了多少次。
传递一个参数作为计数提示:

for (let i = 0; i < 10; i++) {
    console.count('我被调用了');
}
谷歌控制台.png

简单修改一下:

for (let i = 0; i < 10; i++) {
    console.count(`我是${i}我被调用了`);
}
打印效果.png

这个方法意思就是:向控制台写入在同一行使用相同标签调用 count() 的次数。
就是如果你给count()传递的参数值不一样,那么是分开计数的。
再看一个简单的示例:

function fun (name) {
    console.count(name)
}
fun('小米');
fun('小刚');
fun('小米');
效果.png

如果不传递参数,默认的计数提示标签是default字符串:

for (let i = 0; i < 10; i++) {
    // count()没传递提示标签
    console.count();
}

效果.png

一般在某些循环中,如果我们想知道一个函数或者变量被执行或者调用了多少次的时候,可以使用console.count()方法,而通过传递提示标签,我们更可以清晰的知道一个函数分别被不同的情况调用了几次,从而帮助我们定位错误信息。

六、console.time()和console.timeEnd()打印计时

用来跟踪某一个操作的占用时长。
每一个计时器必须拥有唯一的名字,time()的参数名和timeEnd()的参数名要一样。
可以没有参数,默认计时提示为default

// 立即启动计时器
console.time()

// 某些操作
for (let i = 0; i < 10000; i++) {
    // 某些操作             
}

// 立即结束计时器,并输出计时结果
console.timeEnd()
控制台打印效果.png

传递计时器提示:

// 立即启动计时器
console.time('time')

// 某些操作
for (let i = 0; i < 10000; i++) {
    // 某些操作             
}

// 立即结束计时器,并输出计时结果
console.timeEnd('time')
控制台打印效果.png
  • 页面中最多能同时运行10,000个计时器
  • 该方法并不会将结算结果返回到js中,而只是能打印在控制台上。所以不能使用此方法在js中来作为普通计时器使用或者进行性能收集器的一部分。

七、console.dir() 输出以 JavaScript 形式表示的指定对象

如果正在记录的对象是 HTML 元素,将输出其以 DOM 形式表示的属性。
打印一个对象:

// 一个对象
const obj = {
    name: '某某渣',
    age: 22,
    sex: '男'
}

// dir打印
console.dir(obj);

// log打印
console.log(obj);
谷歌控制台效果.png

对于对象或者json等,console.log()和console.dir()效果基本一样。
但是如果打印的是一个dom元素:

// dir打印
console.dir(document.body);

// log打印
console.log(document.body)

console.dir()会将dom的所有属性和事件都被打印出来:

console.dir().png

console.log()打印的就是dom:
console.log().png

八、console.dirxml(object)

如果可以,输出 object 子级元素的 XML 表示形式,否则输出其 JavaScript 表示形式。
在 HTML 和 XML 元素上调用 console.dirxml() 等同于调用console.log()

九、console.group() + console.groupEnd()

将控制台输出的内容进行分组
将打印的信息归类分组打印,并且可以展开、折叠。
这在输出大量数据的或许有用。

// console.groupCollapsed() + console.groupEnd()的形式,默认是折叠的
console.group('分第一组');
console.log('html')
console.dir({ type: '前端'}),
console.groupEnd('分第一组')

// console.group() + console.groupEnd() 默认是展开的
console.group('分第2组');
console.log('php')
console.dir({ type: '后台'}),
console.groupEnd('分第2组')
谷歌打印效果.png

十、console.table()

可以将数组、对象等复杂类型的数据打印成表格的形式
打印简单的数组:

const arr = ['a', 'b']; 
console.table(arr)
效果.png

打印复杂的数组:

const arr = [
   {
       name: '小明',
       age: 22,
       likes: ['跳舞', '上网']
   },
   {
       name: '小刚',
       age: 23,
       likes: ['撸码', '计算机']
   }
];
               
console.table(arr)
效果.png

打印对象:

const obj = {
    name: '小明',
    age: 22,
    likes: [
        {
            a: 1,
            b: 2
        },
        {
            a: 3,
            b: 4
        },
    ]
}
                
console.table(obj)
对象效果.png

十一、console.trace()

堆栈中调用此方法的路径
如果想要清楚地知道一个函数的调用轨迹,可以将此方法写在函数内部,便可以跟踪函数的调用轨迹,代码实现如下:

function test(name) {
    console.trace(`此处调用了${name}`)
}
                
function doSome (name) {
    test(name);
}
                
doSome('翠花');
谷歌控制台打印.png

此处打印出了js中调用test()的所有堆栈位置。从上到下依次为最里层的调用一直到最外层调用。平时我们使用第三方库的时候,如果写法不对,经常可以在控制台看到我们的报错信息,并且像这样打印出了错误位置的堆栈信息。

十二、console.warn()

打印一条警告信息

console.warn('我是一条警告')
谷歌打印结果.png

十三、console.error()打印错误

console.error('我这里出现了错误,我来告知用户')

谷歌打印结果.png

该方法主要用来打印错误,打印结果的样式如上图。也没什么好说的,不过如果你开发第三方库的时候,可以用到。但是throw抛出错误的方式也会用到不少。

十四、console.profile() 和 console.profileEnd()

新建一个性能分析器(基于cpu的使用情况)。用于函数性能分析的利器。
相对于复杂逻辑的JavaScript程序调优,console.profile() 和 console.profileEnd()新建性能分析器便派上用场

用法和time的一样,console.profile()开始,console.profileEnd()结束,需要传递一个参数作为标签使用,说俗了点就是为这个性能分析器起个名字。看下如下代码,我们测试几种不同for循环书写方式的耗时情况:

// 简单新建一个数组吧,新建一个一千万个成员为1的数组
let arr = new Array(10000000).fill(1);
                
// 第一种for循环书写方式             
function fun1 () {
    for (let i = 0, len = arr.length; i < len; i++) {}
}

// 第二种for循环书写方式             
function fun2 () {
    for (let i = arr.length; i --; ) {}
    fun1();
}

// 第三种for循环书写方式     
function fun3 () {
    for (let i = 0, item; item = arr[i++]; ) {}
}

// 执行三个函数       
function fun () {
    fun1();
    fun2();
    fun3();
}

// 立即开始一个性能分析器
console.profile('测试for循环');
fun();
//
console.profileEnd('测试for循环');
谷歌控制台.png

在javascript Profiler面板中,打开性能分析器


打开性能分析器.png

如果你没有上面红框标识的面板,那么点击右边的三个点,在下拉菜单中依次选择More tools -> JavaScript Profiler选项,就可以将该选项添加到上面的红框位置。然后点击该面板,进入对应内容:


性能分析器.png

然后我们点开每一个函数看下具体的情况:
函数具体的情况.png
  • 1处,Self Time表示当前函数自身运行耗时,什么意思?就是说当前函数自身执行耗时,不包括当前函数中调用的其他函数运行耗时。
  • 2处,Total Time表示当前函数运行总耗时,包括了自身运行耗时+函数内部调用的其他函数的执行耗时。
  • Function那一列,我们通过上图打开的fun1那一栏说明,fun1展开后的结果包括funfun2,这指的是函数fun1在函数funfun2中被调用执行的耗时。通过代码我们知道,fun1函数确实在fun函数和fun2个被调用过1次,所以这里展示了fun在这两处被调用执行的耗时时间。
  • 每个函数行最右边还有会堆栈位置,点击即可进入resouce面板中该函数所在的文件位置。

如果你关注fun1函数的执行时间,你可以点击选中fun1这一行,然后点击上面的眼睛图标,将自动只为你展现fun1函数的信息:


眼睛图标.png
  • 选中函数行,点击眼睛即针对性的展示当前函数。
  • 选中函数和,如果点击×号,将会删除当前函数行。
  • 选中函数行点击眼睛进入后,如果想返回到上述全部函数行的面板,可以点击上图刷新按钮。或者删除了函数行后也可以恢复如上图。
  • 上图三个按钮只有在颜色变深的时候才可点击,眼睛和×号只有在选中函数行的情况下可点,刷新按钮在进入或者删除函数行之后可以点。

还有一点没介绍,就是该这种数据展示方式,是默认的方式:Heavy(Bottom Up),即将所有执行的函数,按照耗时长度,从上到下降序排列,耗时的在最上面,不耗时的在最下面。但是他还有另外两种方式(ChartTree),如下图:

数据展示方式.png

Tree型.png

将每个函数行打开后,显示了该函数所调用的函数。这种数据分析的展示方式其实是,先展示最外层的函数,展开后,显示该函数所调用的所有函数,依次往里类推。每一行都展示该函数执行的耗时。其他操作同上。
Chart.png

  • 上部分蓝色区域为cpu占用的大体走势图,可以清晰地看到每个时间节点的cpu占用情况,是高是低一目了然。
  • 下半部分为每个函数开始运行的时间节点。

如果点击上部分蓝色区域,还可以更细粒度查看当前事件的函数运行情况(在当前时间节点划分为更细的力度),如下图:


点击上部分蓝色区域.png

鼠标移入某个函数,还可以看到当前函数所运行的耗时情况,如下图:


当前函数所运行的耗时情况.png

console.profile() 和 console.profileEnd()函数性能分析器的建立,给我们分析函数性能带来的非常大的便利,这对于我们检测程序运行瓶颈非常有帮助。

十五、console.timeStamp('事件信息')

在Performance(以前叫Timeline)性能面板中的会话录制期间插入一条添加一个事件。
说到这个console.timeStamp()方法,这个方法在我们进行性能调试的时候会用到。说到这个方法首先要提到Performance性能面板,因为该方法打印出来的结果需要在这个调试面板中查看,准确的来说,该方法是配合性能面板来调试的:

在Perdormance面板中,我们可以分析当前页面的性能,可以得知页面加载和用户交互相关的事件分析结果。关于Performance这块的内容,如果仔细说起来,内容是比较多的。这里暂且只介绍和console.timeStamp方法相关的内容。以后可以单独把这块拿出来细细分析和记录。

console.timeStamp可以在时间轴上写入一个事件:

// 一些其他操作
for (let i = 0; i < 10000; i ++) {}

// 在录制会话期间插入的第一个事件      
console.timeStamp('第一个循环完了')
                
// 一些其他操作
for (let i = 0; i < 10000; i ++) {}
                
// 在录制会话起价插入的第二个事件
console.timeStamp('第2个循环完了')

录制完会话后,我们输入移入下图红框左上方的黄色竖线上可以看到弹出一个提示框,上面标注了Timestamp提示:‘第一个循环完了’,并且还有该事件插入时的时间节点。


Timestamp.png

十六、console.markTimeline()

效果等同于console.timeStamp(),是console.timeStamp()以前的写法,已经淘汰了。

十七、console.timeLine('标签参数')配合 console.timeLineEnd('标签参数')

录制一段时间的时间轴。
在Performance面板中,我们可以录制当前页面的会话信息,而通过console.timeline和console.timelineEnd可以只录制某一段时间的会话信息。

// 录制第一段时间的会话信息
console.timeline('测试循环100万相关的性能分析')
for (let i = 0; i < 1000000; i ++) {}
console.timelineEnd('测试循环100万相关的性能分析')


// 录制第二段时间的会话信息             
console.timeline('测试循环1000万相关的性能分析')
for (let i = 0; i < 10000000; i ++) {}
console.timelineEnd('测试循环1000万相关的性能分析')

在我们的Performance面板中,点击开始录制当前页面,然后查看录制后的结果:

Performance.png

Performance.png

console.timeline('参数标签')console.timelineEnd('参数标签'),两个方法需要接收相同的一个参数标签,就是一个标识而已。

这里会了这个用法之后,更多的是怎样在Performance中进行性能的分析,然后找出影响程序性能的瓶颈,这才是重要的。

原文链接:调试第一步:让强大的console家族助你一臂之力

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容