先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Web前端全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
如果你需要这些资料,可以添加V获取:vip1024c (备注前端)
正文
当我们在代码里写上一些变量的时候,我们就会向堆中的内存空间进行申请。我们上面说过V8是有内存分配限制的,这是因为V8的垃圾回收机制影响。我们试想一下假如有1.5GB的垃圾需要等待回收,而V8的垃圾回收机制运行一次需要每50毫秒以上,在这段时间内,程序会无法运行。
假如说我非要打开这个限制也不是不行,我们可以在Node的启动时候更改一下参数即可:
node --max-old-space-size=1700 xxx.js //单位是MB
node --max-new-space-size=1024 xxx.js //单位是KB
上面代码的意思就是新生代和老生代空间的更改,稍后解析什么是新生代和老生代空间。
04 V8垃圾回收机制
在V8中,我们知道内存空间可以分为新生代和老生代。新生代空间主要是保存一些存活时间较短的对象,而老生代空间主要存储一些存活时间较长的对象。
之前说过64位系统只能使用约1.4GB,32位只能使用0.7GB的空间。这空间是包含新生代和老生代空间,且老生代的空间比新生代要多。
| | 32位 | 64位 |
| — | — | — |
| 新生代 | 16MB | 32MB |
| 老生代 | 700MB | 1400MB |
V8主要采用两种不同的算法,分别作用于新生代和老生代,因为两者的关系不一样。主要有类算法,第一是Scavenge算法,第二是Mark-Sweep & Mark-Compact。新老生代的特点如下:
新生代:存活对象较少
老生代:存活对象较多
①Scavenge算法
-
把新生代空间一分为二,为From空间和To空间
-
内存先分配到From空间,垃圾回收会检查From空间存活情况
-
把From空间的存活对象移到To空间,释放From空间
-
把From和To空间对换
这就完成了垃圾回收的一次清理过程。
②Mark-Sweep算法
-
遍历堆中的所有对象,标记存活的对象
-
清除没有被标记的对象
由于老生代空间中,存活的对象较多,使用 Scavenge 算法的话遍历的时间会相对来说比较长,而且还会浪费一半的空间来存放对象,效率比较低。总的来说,Scavenge 算法复制存活的对象,而 Mark-Sweep 算法清除死亡的对象。
③Mark-Compact算法
我们看到上面这种算法回收一次过后**产生了零碎的内存空间**,假如这时候进来一个比较大的内存对象就无法完成分配,提前触发新一轮的垃圾回收机制。所以基于这个问题,在原来算法的基础上,采用**压缩**的办法,在标记活对象的过程中,对象会往一边移动。然后标记完成之后直接清除边界的内存。
④Incremental Marking算法
与前面三种不一样的是,这种算法**采用了“步进”的方式**进行,因为垃圾回收机制运行一次的时间也是有的,对于垃圾回收机制运行时间过长,那么页面的应用逻辑都要停下来等待,这种影响也是比较大的。
对于新生代来说不用担心这个问题,因为新生代存活对象比较少,内存占用也比较小。但是对于老生代来说,对象比较多也比较大,停顿造成的影响大,所以必须要让应用逻辑受垃圾回收的影响小一点。
因此采用“步进”的方式,垃圾回收机制和逻辑代码**分段执行**,缓解停顿时间过长而导致应用逻辑执行不了的问题。
关于内存的话我们就不得不聊一下作用域的问题了。我们所写的代码中,可以形成作用域的无非就是几个方面,有函数、with以及全局作用域。
var A = function(){
var user = {}
};
A();
我们在执行这个函数的时候就会创建一个函数作用域,也会创建一个局部的变量user。这个user只能在函数作用域里面使用,函数执行完毕之后作用域销毁,同时对象也失去引用,其引用的对象下次的垃圾回收时就会释放。这里的user是一个小对象,就会分配在新生代的from空间中。
我们知道作用域会有一个作用域链的概念,就是在当前的作用域找不到变量之后就会向父级的作用域寻找,一直向外扩散,找不到就会抛出未定义的错误。
小结:
-
闭包没有及时释放会造成内存泄漏,常见的有
定时器
-
全局变量
,此种变量需要进程退出才会被释放,引用的对象就会在常驻内存
中(老生代
)
V8堆内存相关的指标
我们可以调用process.memoryUsage()查看Node进程的内存使用情况。
heapTotal
(堆中总共申请的内存) 和 heapUsed
(堆中使用的内存) 代表 V8 的内存使用情况。
external
代表 V8 管理的,绑定到 Javascript 的 C++ 对象的内存使用情况。
rss
是常驻空间大小, 是给这个进程分配了多少物理内存(占总分配内存的一部分),包含所有的 C++ 和 JavaScript 对象与代码。
上面我们说过老生代的内存空间
大概在1400MB
左右,为了验证一下,不惜代价搞了一波内存泄漏的操作,看一下到底内存是怎么被消耗掉的。我们手动构造了一个全局的对象,让它放在常驻内存中,也就是老生代中。
function showMemory(j) {
console.log(这是第${j+1}次运行
)
var mem = process.memoryUsage();
function format(bytes) {
return (bytes / 1024 / 1024).toFixed(2) + “MB”;
}
console.log(
`Process:总共申请的内存heapTotal: f o r m a t ( m e m . h e a p T o t a l ) , 目前堆中使用内存 h e a p U s e d : {format(mem.heapTotal)}, 目前堆中使用内存heapUsed: format(mem.heapTotal),目前堆中使用内存heapUsed:{format(
mem.heapUsed
)},常驻内存rss:${format(mem.rss)}`
);
console.log(
“======================================================================================”
);
}
//吃人函数
function useMem() {
var size = 20 * 1024 * 1024;
var arr = new Array(size);
for (var i = 0; i < size; i++) {
arr[i] = 0;
}
return arr;
}
最后
面试题千万不要死记,一定要自己理解,用自己的方式表达出来,在这里预祝各位成功拿下自己心仪的offer。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip1024c (备注前端)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
mg-VXw8Ozid-1713466761581)]
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip1024c (备注前端)
[外链图片转存中…(img-H8QPC3pH-1713466761581)]
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!