垃圾回收内存管理JavaScript不提供操作内存的API,所有的内存操作都是自动的。申请释放什么是不再被引用的垃圾对象对象不能从根访问到可达对象可访问对象(引用,作用域链)标准是能否从根找到JavaScript中的根可以理解为全局变量ObjectGC算法GC是垃圾回收机制的缩写。GC可以找到内存中的垃圾,并释放和回收空间。程序中不再需要的对象。无法在程序中访问的对象。规则引用计算算法核心思想:设置引用计数器,当引用关系发生变化时修改引用数,当引用数为0时立即回收。GC时挂起)缺点不能回收循环引用Object//当fn执行完毕后,obj1和obj2将不再被全局引用,计数器应该为0//但obj1和obj2在方法中仍然存在指向关系,所以counter不为0不能回收functionfn(){constobj1={};constobj2={};obj1.name=obj2;obj2.name=obj1;返回“哈哈”;}fn();时间开销较大(监控和维护计数器)标记清除算法核心思想:划分标记和清除两个阶段。第一阶段方便所有对象标记活动对象(可达对象),第二阶段方便所有对象清除未标记对象,最后回收相应空间。优点与引用计算算法相比,标记清除可以去除不被引用的对象。缺点空间碎片如上图所示,GC运行时,发现只有中间的对象reachable进行标记,左右对象被清除。下次我们分配内存的时候,假设我们需要3个内存域,但是释放出来的空间只有两个,因为是不连续的,需要开辟新的内存空间,造成浪费。标记排序算法的核心思想:标记排序可以看作是标记清除的增强,在标记阶段是完全一致的,在清除阶段会先排序,使空间连续再清除。了解V8V8是主流的JavaScript执行引擎。V8采用即时编译,V8内存限制(64为1.5g/32位800m)。回收策略采用分代回收的思想,将内存分为新生代和老年代。不同的算法用于不同的对象。新生代新生代是指存活时间短的对象(局部作用域等)。小空间用户在回收过程中存放新生代对象(32M|16M)。回收过程采用复制算法+标记。新一代将内存分成两个大小相等的空间。已用空间为From,可用空间为To。活动对象存储在From空间中。整理后,将活动对象复制到ToFrom,释放From和To交换空间,完成释放。注意:一轮GC存活下来的新生代需要提升(将新生代对象移动到老年代),To空间使用率超过25%。提升到老年代放在右边的老年代区(1.4G|700G)。老年代对象是指存活时间较长的对象(全局属性、闭包等)。回收过程主要使用标记清除、标记排序和增量标记算法。使用标记清除完成垃圾空间回收使用标记排序进行空间优化(提升)使用增量标记进行效率优化(GC和程序交替)与新生代区域垃圾收集相比使用空间换时间老年代区域垃圾收集不适合复制算法,由于数据量大,性能优化缓存数据,降低访问级别,降低判断级别,减少循环体活跃度和节流。设置频率,让本来可以触发多次的事件按照我们定义的频率执行。varoBtn=document.getElementById("btn");/***处理需要执行的事件*等待事件触发后多久开始执行*立即控制是第一次执行还是最后一次执行**/functionmyDebounce(handle,wait=1000,immediate=false){lettimer=null;返回函数代理(){clearTimeout(计时器);constinit=immediate&&!timer;//immediate=false表示最后一次执行触发timer=setTimeout(()=>{timer=null;!immediate?handle():null;},wait);//immediate=true表示执行时第一次触发//立即执行也依赖于setTimeout控制时间,定时器为空时执行init?句柄():空;};}functionbtnClick(){console.log("clicked");}oBtn.onclick=myDebounce(btnClick,500,true);throttlingfunctionscrollFn(){console.log("scrolled");}/***waitfrequency*nowcurrenttime*perviouslastexecutiontime*wait-(now-previous)*如果上面的计算结果大于0,then表示当前操作是高频的,我们得想办法不让他执行handle*如果小于0,就是非高频的,那么handler就可以了直接触发**/functionmyThrottle(handle,wait=1000){letprevious=0;//最后一次执行时间lettimer=null;returnfunctionproxy(){letnow=newDate();}//当前执行时间letinterval=wait-(now-previous);if(interval<=0){//非高频可以立即执行//防止浏览器监听触发的事件和我们节流的时间重合,只取第一个ifclearTimeout(timer);定时器=空;处理();前一个=新日期();}elseif(!timer){//当系统中已经有定时器等待时,则不需要再启动定时器//高频,等待间隔执行timer=setTimeout(()=>{clearTimeout(timer);//定时器清零,但定时器值仍为timer=null;handle();previous=newDate();},间隔);}};}window.onscroll=myThrottle(scrollFn,2000);
