识别并避免 Js 内存泄漏,跟低级缺陷say goodbye,让老总对你刮目相看

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Golang全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024b (备注go)
img

正文

function fn() {

msg = “这是一个意外的全局变量”;

}

函数 fn 内部忘记使用 var ,实际上 js 会把 msg 挂载到全局对象上,意外创建一个全局变量。

类似

function fn() {

window.msg = “这是一个显式定义的全局变量”;

}

另一种意外的全局变量可能由 this 创建

function fn() {

this.msg = “该this指向window,创建了一个全局变量”;

}

// fn 调用自己时,this 指向了全局对象(window),而不是 undefined

fn();

如何避免

在 JavaScript 文件头部加上 “use strict” ,使用严格模式避免意外的全局变量,此时上例中的this指向undefined。如果必须使用全局变量存储大量数据时,确保用完以后把它设置为 null 或者重新定义

2、被遗忘的定时器或回调函数

定时器setInterval、setTimeout代码很常见

let data = getData();

setInterval(() => {

let el = document.getElementById(‘El’);

if(el) {

// 处理 el 和 data

el.innerHTML = JSON.stringify(data);

}

}, 1000);

以上例子中,在 el 或者数据不再需要时(如节点移除),定时器仍然指向这些数据。所以就算 el 节点被移除后,setInterval 仍旧存活且垃圾回收器没办法回收,它的依赖自然也没办法被回收,除非终止定时器,如

let data = getData();

let timerId = setInterval(() => {

let el = document.getElementById(‘El’);

if(el) {

// 处理 el 和 data

el.innerHTML = JSON.stringify(data);

}

}, 1000);

// 终止定时器,使得它的依赖(el、data)可被回收

clearInterval(timerId)

// setTimeout使用clearTimeout()

补充

let btn = document.getElementById(‘button’);

function onClick(event) {

btn.innerHTML = ‘text’;

}

btn.addEventListener(‘click’, onClick);

对于监听绑定,一旦它们不再需要(或者关联的对象变成不可达),明确地移除它们非常重要。老的 IE 6 是无法处理循环引用的。因为老版本的 IE 是无法检测 DOM 节点与 JavaScript 代码之间的循环引用,会导致内存泄漏。

// 明确移除监听器

btn.removeEventListener(‘click’, onClick);

但是,现代的浏览器(包括 IE 和 Microsoft Edge)使用了更先进的垃圾回收算法(标记清除),已经可以正确检测和处理循环引用了。即回收节点内存时,不必非要调用 removeEventListener 了。

3、脱离DOM的引用

如果把DOM 存成字典(JSON 键值对)或者数组,此时,同样的 DOM 元素存在两个引用:一个在 DOM 树中,另一个在字典中,那么将来需要把两个引用都清除

// 创建一个elements,依赖#button与#image

let elements = {

button: document.getElementById(‘button’),

image: document.getElementById(‘image’),

};

function doStuff() {

let image = document.getElementById(‘image’);

image.src = ‘http://some.url/image’;

let button = document.getElementById(‘button’);

button.click();

// …

}

function removeButton() {

// 按钮是 body 的后代元素

document.body.removeChild(document.getElementById(‘button’));

// 此时,仍旧存在一个全局的#button的引用elements字典。button元素仍旧在内存中,不能被GC回收。

}

// 显式移除引用,elements = null,使依赖的DOM可被GC回收

如果代码中保存了表格某一个 <td> 的引用。将来决定删除整个表格的时候,直觉认为 GC 会回收除了已保存的 <td> 以外的其它节点。实际情况并非如此:此 <td> 是表格的子节点,子元素与父元素是引用关系。由于代码保留了 <td> 的引用,导致整个表格仍待在内存中。所以保存 DOM 元素引用的时候,要小心谨慎。

4、闭包

闭包的关键是内部函数可以访问父级作用域的变量

let theThing = null;

let replaceThing = function () {

let originalThing = theThing;

let unused = function () {

if (originalThing)

console.log(“hi”);

};

theThing = {

longStr: new Array(1000000).join(‘*’),

someMethod: function () {

console.log(someMessage);

}

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Go)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
unction () {

console.log(someMessage);

}

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Go)
[外链图片转存中…(img-YZwM9wDd-1713602925852)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值