这是我参与更文挑战的第19天,活动详情查看: 更文挑战
控制台 console.log() 打印很多日志,会不会影响浏览器卡顿?
为什么要写这篇文章,接手了一个老项目,需要对项目的性能进行优化,打开F12发现,console.log()写的内容太多,多到你不敢想象,这还是次要的,上线的代码,debugger,到处都是,整个系统,每天用户使用到下午三四点的时候开始卡顿,CTRL+SHIFT+DELETE之后,速度又快了,种种迹象表明,肯定是有内存泄露的情况,因为是老系统,前后端不分离,首先要说服负责人,上线代码删除console.log, 今天不讲解怎么删除线上代码console.log, 先分析一下,为什么线上代码要删除console.log
console.log() 目的是向浏览器控制台打印信息, 常用来在开发的时候调试分析,但是很多人在上线的代码里面忘记关闭了, 导致打印信息不停的输出。
(1) console.log: 可能导致内存泄露
(2) console.log: 在传递给console.log的对象是不能被垃圾回收
(3) console.log: 它属于宏任务,在执行的时候,也是需要耗时
结合Chrome的 F12中的Performance 进行一些分析, 勾选上Memory, 通过带有console.log的输出和没有console.log的输出,对比分析结果: 最好不要在页面中进行console.log的大对象输出,会影响到页面的整体性能。
1, console.time
通常我们查看一段代码的执行时间,用来作性能调试分析所用。
首先记住:console.log 对象不会被浏览器垃圾回收机制回收 会造成浏览器卡顿
console.time()相当于秒表中的开始按钮
console.timeLog()相当于秒表中的按圈计时/按点计时
console.timeEnd()相当于计时结束
console.time('time')
console.log(JSON.parse(JSON.stringify(new Object())))
console.timeEnd('time')
打印:time: 1.572021484375ms
console.time('time')
setTimeOut(() => {
console.timeEnd('wait')
}, 1000)
wati: 1000ms
2, console.count
这是一个计数器, 传递一个函数的名称,可以打印出这个函数被调用的次数
let a = () => {
console.count('调用a')
}
let b = () => {
console.count('调用b')
}
a()
b()
输入: 调用a:1
调用b:1
3, console.assert
断言, 可以理解为: 才猜错了这个表达式的真假,那我就可以打出我的信息
console.assert(参数1,参数2), 这里面有两个参数:
第一个参数:是断言条件,即应该发生的情况;
第二个参数:是不满足断言条件时,打印出来的提示信息。
console.assert(a === 3, "a 的值不是3!");
断言函数还是挺有用的,就算不是为了做单元测试,自己平时在写代码时为了保证程序正确性,也可以使用一下。可以让我们的输出更加干净。当然,你也可以写if判断语句。
4, console.clear
这个函数也是经常用,在多人开发的项目里面,特别是很多项目小组成员都喜欢打印console.log的时候,你在调试的时候,特别不想看到他们的结果,统统都可以用console.clear清楚干净,那后输出自己的调试信息。
console.clear()
console.log(data)
5, console.dir
在大多数情况下,console.dir()和console.log() 看起来很像,在打印DOM元素信息的时候,你会发现,dir会输出的更加详细
举个列子:查看element信息
let element = document.getElementById('root')
console.log(element)
<div class="root">
<img class="ssse" src="https:/xxxx">
<meta itemprop="commentCount" content="24"></meta>
<div class="ble">
<div class="Rtr">
<span class="Rix">Vue</span><span class="p">,</span>
</div>
</div
</div>
console.dir(element)
div#root
accessKey: ""
align: ""
assignedSlot: null
attributeStyleMap: StylePropertyMap {size: 0}
attributes: NamedNodeMap {0: id, id: id, length: 1}
autocapitalize: ""
baseURI: "https://www.zhihu.com/question/61986999"
childElementCount: 1
childNodes: NodeList [div]
children: HTMLCollection [div]
classList: DOMTokenList [value: ""]
className: ""
clientHeight: 2763
clientLeft: 0
clientTop: 0
clientWidth: 743
contentEditable: "inherit"
dataset: DOMStringMap {}
dir: ""
draggable: false
firstChild: div
firstElementChild: div
hidden: false
id: "root"
innerHTML: "<div><div class="LoadingBar"></div><div><header ro"
inputMode: ""
isConnected: true
isContentEditable: false
lang: ""
lastChild: div
lastElementChild: div
localName: "div"
namespaceURI: "http://www.w3.org/1999/xhtml"
nextElementSibling: script#js-clientConfig
nextSibling: script#
6, console.warn
可以直接替换console.log,他们都是输出,唯一的区别就是:输出的文字颜色是黄色, 具体来说,如果给日志定义错误级别的话,它的输出属于警告级别,而不是信息级别, 使其在众多日志中输出会显示的更加明显,突出
console.warn('这是一个警告')
输出是:黄色字体,这是一个警告⚠️
7, console.log, debugger的区别
这些都可以用来调试。
debuuger: 在指定的代码处,添加debugger, 或者打开浏览器的F12, 在指点的地方添加F12,通过执行项目,一步步观察变量和函数的执行过程
Console.log: 在指点的函数和变量的地方添加console.log, 把向查看的结果dayin 在浏览器控制台上,进行过程分析, 两者都能加快我们的开发
在准确率上来说, console..log的准确率要高于debugger, 因为在我们的代码中,有很多异步事件,也有很多监听方法,或者是生命周期函数,他们的执行顺序或决定这变量值的存储,影响到不同的执行结果,debugger无法查看代码的执行顺序, 可能会给自己带来无法想象的问题,本人就在这个问题上吃过几次亏, 因为打来debugger 会加快一些异步请求的速度,实际上,如果没有这些debugger, 异步请求是没有完成的。这样会导致我们开发的时候,功能都是正常的,为什么上了测试或者上生产就会有问题的原因
个人建议: 简单功能,可以通过浏览器debugger断点查看
复杂功能,涉及到一些异步请求,事件监听或者是生命周期函数,最好是用console.log就行调试,当然,
调试完成之后,一定要养成删掉的习惯。
8, 总结
测试通过的代码,即将发到生产环境上的代码,要避免有大量的console.log日志输出,它会影响到页面的性能,有可能会造成内存泄露, 开发的过程中可以养成用console.log的习惯, 在有异步接口请求,或者多个事件监听发送的代码中,尽量不要用debugger排查问题。