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

2018-10-11  本文已影响41人  alanwhy

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

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


console.png

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

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

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

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

补充修正: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.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

七、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

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


眼睛图标.png

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

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

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


点击上部分蓝色区域.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家族助你一臂之力

上一篇 下一篇

猜你喜欢

热点阅读