最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • JavaScript性能优化

    正文概述 掘金(德善啊)   2021-01-26   549

    前言:代码为什么需要优化?

    • web应用日益丰富,用户体验至关重要,前端性能备受关注
    • 实现相同的结果下,哪种类型JavaScript代码具有更高性能
    • 高性能的背后是数据快速存取,也是优秀内存管理的体现

    JavaScript内存管理(Memory Management):

    • 内存:有可读写的单元组成,表示一片可操作空间
    • 管理:人为的去操作一片空间的申请、使用和释放
    • 内存管理:开发者主要申请空间、使用空间、释放空间
    • 管理流程:申请 - 使用 - 释放

    JavaScript中的垃圾回收:

    • JavaScript中内存管理是自动的
    • 对象不再引用时被视为垃圾
    • 对象不能从根上访问到时是垃圾

    JavaScript中的可达对象:

    • 可以访问到的对象就是可达对象
    • 可达的标准就是从根出发是否能够被找到
    • JavaScript中的根就可以理解为是全局变量对象

    GC算法介绍:

    • GC的定义与作用:GC垃圾回收机制的简写;GC可以找到内存中的垃圾、并释放和回收空间
    • GC里的垃圾:程序中不再需要使用的对象,程序中不能再访问到的对象
    • GC算法:
      • GC是一种机制、垃圾回收器完成具体的工作;
      • 工作的内容就是查找垃圾释放空间、回收空间
      • 算法就是工作时查找和回收所遵循的规则

    常见的GC算法:

    引用计数:
    • 核心思想:设置引用数,判断当前引用数是否为0,引用计数器,引用关系改变时修改引用数字,引用数字为0时立即回收;

    • 优点:发现垃圾时立即回收,最大限度减少程序暂停

    • 缺点:无法回收循环引用的对象;时间开销大;资源消耗大;

    标记清除:
    • 核心思想:分标记和清除两个阶段完成,遍历所有对象标记活动对象,遍历所有对象标记清除未标记对象,回收相应空间;

    • 优点:可回收循环引用的对象

    • 缺点:不能立即回收垃圾对象,空间碎片化(回收后的空间不连续)

    标记整理
    • 核心思想:标记整理可以看做是标记清除的增强,标记阶段的操作和标记清除一致,清除阶段会先执行整理,移动对象的位置,再进行清除并回收

    • 优点:减少碎片化空间

    • 缺点:不可立即回收

    分代回收:内存分为新生代、老生代,针对不同对象采用不同算法,具体见V8垃圾回收机制

    关于V8:

    认识V8:

    • 一款主流的JavaScript执行引擎
    • V8采用即时编译(速度快)
    • V8内存设限(64位为1.5G,32位为800M)

    V8垃圾回收策略:

    • 采用分代回收的思想:内存分为新生代、老生代,针对不同对象采用不同算法

    • V8中常用GC算法:分代回收、空间复制、标记清除、标记整理、标记增量

    • V8如何回收新生代对象:新生代指的是存活时间较短啊的对象;

      • 内存分配:V8内存一分为二,小空间用于存储新生代对象(32M/16M);
      • 新生代对象回收实现:复制算法+标记整理 => 新生代内存区分为两个等大的内存空间,使用空间From,空闲空间To => 活动对象存储于From空间 => 标记整理后将活动对象拷贝至To => From 与 To交换空间完成释放
      • 回收细节说明:拷贝过程中可能出现晋升,就是将新生代对象移动至老生代,一轮GC还存活的新生代需要晋升,To空间的使用率超过25%
    • V8如何回收老生代对象:老生代指的是存活时间较旧的对象

      • 老生代对象回收实现:主要采用标记清除、标记整理、增量标记算法;首先采用标记清除完成垃圾空间的回收,采用标记整理进行空间优化,采用增量标记进行效率优化;(标记增量:由于垃圾回收会阻塞js代码执行,所以回收机制会将任务拆分进行操作)
    • 关于新生代对象与老生代对象回收细节的对比:

      • 新生代区域垃圾回收使用空间换时间(本身空间小,时间提升大)
      • 老生代区域垃圾回收不适合复制算法(老生代对象数据较大,空间较大)

    Performance工具介绍:

    为什么要是用Performance?

    • GC的目的:实现内存空间的良性循环(空间的合理分配)
    • Performance提供多种监控方式,时刻关注才能确定空间使用是否合理,则Performance可以时刻监控内存

    内存问题的体现:

    • 延迟加载/经常性暂停(频繁的垃圾回收)
    • 持续性糟糕的性能(内存膨胀 => 申请内存空间大小超过内存本身提供大小)
    • 性能随时间延长越来越差(内存泄漏)

    界定内存问题的标准:

    • 内存泄漏:内存使用持续升高(无下降节点)
    • 内存膨胀:当前应用程序本身为达到最优效果,需要很大的内存空间,也许是硬件,程序or设备,在不同设备上运行测试
    • 频繁的垃圾回收:通过内存变化图进行分析

    监控内存的几种方式:

    • 浏览器任务管理器
    • Timeline时序图记录
    • 堆快照查找分离DOM
    • 判断是否存在频繁的垃圾回收

    判断是否存在频繁GC:

    • GC工作时应用程序是停止的
    • 频繁且过长的GC会导致应用假死
    • 用户使用中感知应用卡顿

    代码优化具体操作:

    • 慎用全局变量,全局变量持续占用内存,明确数据作用域的情况下,尽量用局部变量,减少全局查找时间消耗
    • 通过原型新增方法:在原型对象上新增实例对象需要的方法
    • 避开闭包陷阱:闭包使用不当很容易造成内存泄露
    • 避免属性访问方法使用
    • 采用最优循环方式:for循环优化(例1)
    //例1:
    var arrList = []
    arrList[10000] = 'icoder'
    for (var i = 0; i < arrList.length; i++) {
      console.log(arrList[i])
    }
    // 用下述方法代替上面的,减少js运算过程
    for (var i = arrList.length; i; i--) {
      console.log(arrList[i])
    }
    
    //例2:该案例中最优循环forEach()
    var arrList = new Array(1, 2, 3, 4, 5)
    
    arrList.forEach(function(item) {
      console.log(item)
    })
    
    for (var i = arrList.length; i; i--) {
      console.log(arrList[i])
    }
    
    for (var i in arrList) {
      console.log(arrList[i])
    }
    
    • 节点添加优化:将查找的固定节点提前定义,在循环中不必每次都去查找
    // 优化前:
    for (var i = 0; i < 10; i++) {
    	var oP = document.createElement('p')
    	oP.innerHTML = i
    	document.body.appendChild(oP)
    }
    
    // 优化后:
    const fragEle = document.createDocumentFragment()
    for (var i = 0; i < 10; i++) {
        var oP = document.createElement('p')
        oP.innerHTML = i
        fragEle.appendChild(oP)
    }
    
    document.body.appendChild(fragEle)	
    
    • 克隆优化节点操作:通过clone不必每次创建DOM
    // 优化前:
    for (var i = 0; i < 3; i++) {
      var oP = document.createElement('p')
      oP.innerHTML = i 
      document.body.appendChild(oP)
    }
    
    // 优化后:
    var oldP = document.getElementById('box1')
    for (var i = 0; i < 3; i++) {
      var newP = oldP.cloneNode(false)
      newP.innerHTML = i 
      document.body.appendChild(newP)
    }
    
    • 直接量替换Object操作:多用字面量定义
    • 减少判断层级:
      • 明确枚举值的情况下使用switch - case 判断
      • 避免多层嵌套,固定的条件结果提前判断return
    • 减少作用域链查找层级:在作用域链内部定义变量,多用const,let辅助,尽量不使用var
    • 减少数据读取次数:缓存数据(会有内存消耗)
    • 字面量与构造式:字面量性能高于构造式(引用类型差异无大)
    • 减少声明与语句数:不是每次都用到的数据,不需要进行缓存,直接return
    • 惰性函数与性能:使用惰性函数提升性能
    • 采用事件委托:利用js事件冒泡机制,把原本需要绑定在子元素上的响应事件委托给父元素,父元素完成事件监听,减少事件子元素的事件注册。

    结语:以上内容全学习时手敲记录,无复制粘贴,全原创,希望可以给各位小伙伴带来收获,如有错误的地方或有疑问欢迎留言,感谢阅读!


    祝各位前端程序猿前程似锦,一路向北!


    起源地下载网 » JavaScript性能优化

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元