这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

很多前端都喜欢用 console.log 调试,先不谈调试效率怎么样,首先 console.log 有个致命的问题:会导致内存泄漏。

为什么这么说呢?

用 Performance 和 Memory 工具分析下就知道了。

我们准备这样一段代码:

一个按钮,点击之后创建一个数组,执行一些计算。

很常见的逻辑。

我们最后加了一个 console.log 打印了下这个数组。

起个静态服务:

浏览器访问:

点击 performance 下的垃圾回收按钮,手动触发一次 GC:

勾选 Memory,然后开始录制,点击 3 次按钮,再执行一次 GC:

你会发现内存是这样的:

内存占用有三次增长,因为我们点击三次按钮的时候会创建 3 次大数组。

但是最后我们手动 GC 之后并没有回落下去,也就是这个大数组没有被回收。

按理来说,代码执行完,那用的内存就要被释放,然后再执行别的代码,结果这段代码执行完之后大数组依然占据着内存,这样别的代码再执行的时候可用内存就少了。

这就是发生了内存泄漏,也就是代码执行完了不释放内存的流氓行为。

有同学说,只是这么一点内存问题不大呀,反正可用内存还很多。

但如果你的代码要跑很长时间,这段代码要执行很多次呢?

每次执行都会占据一部分内存不释放,慢慢的内存就不够用了,甚至会导致程序崩溃。

比如当这段代码执行个 9 次,内存占用就增长了 9 个大数组的内存:

再多执行几次呢?

是不是就有崩溃的隐患了。

那为啥说是 console.log 导致的呢?

我们来看看不用 console.log 是什么样的:

注释掉 console.log,重新跑。

你会发现现在的内存分配情况是这样的:

分配了三次内存,但是 GC 后又会落下去了。

这才是没有内存泄漏的好代码。

那为啥 console.log 会导致内存泄漏呢?

因为控制台打印的对象,你是不是有可能展开看?那如果这个对象在内存中没有了,是不是就看不到了?

所以有这个引用在,浏览器不会把你打印的对象的内存释放掉。

有的同学说,那我不打开控制台,是不是就没有这个引用了?

答案是否定的:

我点击了几次之后,再打开控制台,依然是可以看到这个对象的,说明没有被 GC。

也就是说用 console.log 打印对象的代码一定是有内存泄漏的。

当然,也不只是 console.log 会导致内存泄漏,还有别的 4 种情况:

  • 定时器用完了没有清除,那每次执行都会多一个定时器的内存占用,这就是内存泄漏
  • 元素从 dom 移除了,但是还有一个变量引用着他,这样的游离的 dom 元素也不会被回收。每执行一次代码,就会多出游离的 dom 元素的内存,这也是内存泄漏
  • 闭包引用了某个变量,这个变量不会被回收,如果这样的闭包比较多,那每次执行都会多出这些被引用变量的内存占用。这样引用大对象的闭包多了之后,也会导致内存问题
  • 全局变量,这个本来就不会被 GC,要注意全局变量的使用

总之,全局变量、闭包引用的变量、被移除的 dom 依然被引用、定时器用完了没清除、console.log 都会发生代码执行完了,但是还占用着一部分内存的流氓行为,也就是内存泄漏。

注意,这里指的是使用完毕后没有回收,在使用期间的内存增长是正常的。

那怎么排查呢?

performance 工具就可以:

点击内存分配情况的某个点,就会定位到 performance 中的某个任务的代码,点击可以在下面看到详情:

这样就定位到了分配内存的代码,分析一下哪里会有问题即可。

当然,前提还是要执行先 GC,再做一些操作,再 GC 的这个流程。

这是从代码角度来分析内存泄漏,其实还可以从内存中对象的角度,这个是通过 Memory 工具:

先 GC,录制一次内存快照,再点击几次按钮,然后 GC,再录制一次内存快照。

流程和用 performance 分析的时候一样。

拿到两次内存快照也是可以分析出有内存泄漏的:

可以看到 GC 后内存占用依然增长了。

快照记录着这个时刻内存中所有对象的状态:

对比两次快照,就可以找到变化的部分:

比如这时候可以看到最大的内存增长是 array 对象:

然后就可以从 array 的角度去思考是什么导致的内存泄漏了。

此外,memory 还有实时分析的工具:

选择第二个,然后点几次按钮:

其实不用手动 GC,JS 引擎会做 GC。

去掉 console.log 再录制是这样的:

除了最开始全局变量会分配一些内存以外,点击按钮之后的内存变蓝后又变灰了,也就是被 GC 了。

这样你点多少次按钮,内存占用都没有增长。

这就是代码执行完,会回收所有用到的内存的好代码。

而前面的那个是每次代码执行,都会占用一部分内存不释放的内存泄漏代码。

你还可以看到每一次内存分配的对象是啥:

不管是用 Performance 工具还是 Memory 工具,都可以发现 console.log 有内存泄漏的问题。所以还是尽量不要用这个来调试了。

那应该用什么呢?

用 debugger 呀,不管是 vscode debugger 还是 chrome devtools 的都可以:

你可以添加一个 logpoint 来代替 console.log 打印:

代码执行到这里就会打印:

而你的代码里不需要写 console.log。

此外,很多地方可以用断点代替打印:

可以看到代码执行路线和作用域,岂不是更高效?

总结

console.log 会导致内存泄漏,也就是代码执行完了,但还占据着一部分内存的流氓行为。

除了 console.log,游离的 dom 被变量引用、全局变量、变量被闭包引用、定时器没清除也会导致内存泄漏。

我们可以用 Performance 工具和 Memory 工具分析内存泄漏。

先手动 GC,然后执行一些操作,再 GC,如果内存没有回到执行前,就说明这段代码有内存泄漏,可以再用 Performance 定位到代码位置分析代码。

Memory 工具是从内存对象的角度分析,可以对两次快照做 diff,看下是啥对象泄漏了。

也可以实时检测内存占用情况,看看是否存在内存泄漏,对象是啥。

console.log 调试效率也不高,可以换成 logpoint,或者打断点。

千万不要把 console.log 上生产!不然这样有内存泄漏的代码,一旦执行时间长了就会有问题。

其实普通项目也还好,不会长期跑,但是类似大屏项目这种长期跑的,一旦有内存泄漏,一定会崩溃,只有时间长短的区别。

本文转载于:

https://juejin.cn/post/7185128318235541563

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

记录--千万别让 console.log 上生产!用 Performance 和 Memory 告诉你为什么的更多相关文章

  1. vue生产环境清除console.log

    npm run build 后的生产环境的代码,会有很多开发时留下的console.log(),不可能每个页面不停地删除 在build/webpack.prod.conf.js文件里加上这样一段代码即 ...

  2. vue在生产环境清除console.log

    在开发环境中我们喜欢用console.log测试代码,但是部署到生产环境我们不可能一个一个把console.log给手动删除了. 在build/webpack.prod.conf.js文件里加上这样一 ...

  3. vue-cli2.0和vue-cli3.0中当发布到生产环境时禁用console.log

    vue-cli2.0中的方法 1.安装插件 npm install uglifyjs-webpack-plugin --save-dev 2.修改webpack.prod.conf.js配置文件 co ...

  4. Javascript的console.log()用法

    Firebug & Chrome Console 控制台的一些其他功能console.log(object[, object, ...])使用频率最高的一条语句:向控制台输出一条消息.支持 C ...

  5. 前端不为人知的一面--前端冷知识集锦 前端已经被玩儿坏了!像console.log()可以向控制台输出图片

    前端已经被玩儿坏了!像console.log()可以向控制台输出图片等炫酷的玩意已经不是什么新闻了,像用||操作符给变量赋默认值也是人尽皆知的旧闻了,今天看到Quora上一个帖子,瞬间又GET了好多前 ...

  6. 小谈chrome调试命令:console.log的使用

    相信从事前端开发的您,一定不会陌生Mozilla五星级推荐的一款插件:firebug,它是如此强大,乃至于我们可以很方便地调试DHTML的近乎所有元素.而在它深邃的机体里,还存有一个命令:consol ...

  7. console.log 用法

    转自http://www.cnblogs.com/ctriphire/p/4116207.html 大家都有用过各种类型的浏览器,每种浏览器都有自己的特色,本人拙见,在我用过的浏览器当中,我是最喜欢C ...

  8. 推荐前端开发手机调试打印神器console.log()

    下面说的这个插件很牛,相信很多人都不知道,但找问题的时候很需要,直接上干货如下: vConsole:一个轻量.可拓展.针对手机网页的前端开发者调试面板. 下载 vConsole 的最新版本.(不要直接 ...

  9. 【转】console.log 用法

    标签: 转自http://www.cnblogs.com/ctriphire/p/4116207.html 大家都有用过各种类型的浏览器,每种浏览器都有自己的特色,本人拙见,在我用过的浏览器当中,我是 ...

  10. js调试console.log使用总结图解

    一 实例 打印字符串和对象: 可展开对象查看内部情况: 看一下console对象本身的定义情况: 输出对象情况: utag对象所在文件: 输出对象: 二 Console.log 总结 1   如果你j ...

随机推荐

  1. Android架构组件LiveData

    LiveData LiveData是基于观察者模式创建的,其中,LiveData是被观察者,观察者通过注册方法,监听被观察者的数据变化.LiveData在数据发生变化的时候,会通知观察者. LiveD ...

  2. nginx 配置stream模块代理并开启日志配置

    前言 nginx 1.20.1nginx从1.9.0开始,新增加了一个stream模块确保nginx 安装时开启stream模块 ./configure \ -- \--with-stream \ - ...

  3. 深入 Nginx 之架构篇[转]

    前言 最近在读 Nginx 相关的书籍,做一下读书笔记. Nginx 作为业界知名的高性能服务器,被广泛的应用.它的高性能正是由于其优秀的架构设计,其架构主要包括这几点:模块化设计.事件驱动架构.请求 ...

  4. 适用于Spring Boot Jar的启停部署脚本

    shell脚本参数 使用-z或-n对一个变量判空时, 若直接使用[ -n ARG ]这种形式,当{ARG}中有空格将会报错, line 27: [: sd: binary operator expec ...

  5. python第二章pta习题总结

    chapter2 一.选择填空判断部分 1. C语言中,变量变的是内存空间中的值,不变的是地址: Python中,变量变的是地址,不变的是内存空间中的值. 2. 3.bool('False') 的返回 ...

  6. 《深入理解Java虚拟机》(八) 记录一次OOM问题分析实战

    目录 一.问题分析思路 二.主要问题概述以及分析 1.相关操作 2.主要问题现象 3.初步分析问题 三.相关工具介绍 四.实际问题快照分析 1.通过Memory查看老年代内存占用情况 2.选择Live ...

  7. 【Android逆向】frida 破解 滚动的天空

    1. apk 安装到手机中 2. 玩十次之后,会提示 充值 3. adb shell dumpsys window | grep mCurrentFocus 查看一些当前activity是哪一个 是 ...

  8. 前后端分离解决跨域cors问题

    修改windows的hosts文件 vim C:\Windows\System32\drivers\etc\hosts 添加域名 前端:www.luffycity.cn 后端:api.luffycit ...

  9. 李宏毅2022机器学习HW4 Speaker Identification上(Dataset &Self-Attention)

    Homework4 Dataset介绍及处理 Dataset introduction 训练数据集metadata.json包括speakers和n_mels,前者表示每个speaker所包含的多条语 ...

  10. ConfigMap挂载与Subpath在Nginx容器中的应用

    本文分享自华为云社区<nginx.conf以configmap文件形式挂载到nginx容器中以及subpath使用场景>,作者:可以交个朋友. 背景 nginx.conf通过configm ...