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

    正文概述 掘金(云伴风轻舞)   2021-01-26   504

    1.为什么要优化JavaScript的性能?

           性能是创建网页或应用程序时最重要的一个方面,没有人想要应用程序崩溃或者网页无法加载,或者用户的等待时间过长。大部分用户希望网站在2秒以内加载完成,如果加载过程需要 3 秒以上,则有 超过50%的用户会离开网站。

           所以为了对这种状况进行改善,JavaScript的应用可谓是重中之重,对它的性能优化自然也凸显得尤为重要。

    2.DOM 对JavaScript是最贵的性能开销,没有之一

    首先,先让我们来了解一下什么是DOM:

    DOM 是 W3C(万维网联盟)的标准。

    DOM 定义了访问 HTML 和 XML 文档的标准:

    W3C DOM 标准被分为 3 个不同的部分:

    • 核心 DOM - 针对任何结构化文档的标准模型
    • XML DOM - 针对 XML 文档的标准模型(XML DOM 定义了所有 XML 元素的对象和属性
      ,以及访问它们的方法。)
    • HTML DOM - 针对 HTML 文档的标准模型(HTML DOM 定义了所有 HTML 元素的对象和属性,以及访问它们的方法。)

          简而言之,DOM就是文档对象模型,而HTML的文档document页面是一切的基础,没有它DOM就无从谈起。当创建好一个页面并加载到浏览器时,DOM就悄然而生,它会把网页文档转换为一个文档对象,主要功能是处理网页内容。 在这个文档对象里,所有的元素呈现出一种层次结构,就是说除了顶级元素html外,其他所有元素都被包含在另外的元素中。 

    其次,JavaScript使用DOM元素性能开销大

    使用JavaScript访问DOM元素很容易,代码更容易阅读,但是JS访问DOM元素没有我们想象的那么快,元素越多访问速度越慢。

    这里做一个使用DOM元素的小测试,执行输出10000条数据:

    <div id="container"></div>    
    <script>       
     for(var count=0;count<10000;count++){            
    document
         .getElementByid('container')
         .innerHTML+='<span>DOM小测试</span>;       
     }    
    </script>
    

    通过Chrome浏览器打开后,会发现页面在不停地加载,过了相对比较长的一段时间才能加载出10000条数据,电脑要是性能差一些,页面会直接呈现无法响应的状态。

    浅谈JavaScript性能优化

    问题来了,为什么会这样呢?怎样优化?

    因为数据执行了10000次吗?的确有这方面的原因 ,执行1次和执行10000 次,消耗的内存自然是不一样的 ,后者的内存花销更大,但是主要的原因并不是在这,我们先从优化的角度分析一下问题出现的原因,并解决问题。

    - 一般来说,加载一个HTML页面是很快的,但是执行10000条数据后,页面却处于在不停地      加载状态。但其实这个HTML页面已经加载完成,不过其中的JS却堵塞了,要花时间等着JS执    行完成,这也是因为JS是一个单线程语言,它如果不执行完成,那么这个页面就会一直呈现      加载状态,造成的结果有两种,一种是页面加载超时,另一种是Chrome浏览器被限制使用      内存。

    - 内存消耗在哪里呢?让我们分析一下代码,首先是for循环:

    for(var count=0;count<10000;count++)
    

      看上去循环10000次会消耗大量内存,但实际上不是,循环10000次其实是在短短1ms内完成,在操作系统CPU中,CPU运算时间是非常快速的。

      真正消耗大量内存的是document ,它才是主要的性能开销来源:

     document
                    .getElementByid('container')
                    .innerHTML+='<span>DOM小测试</span>;
    

      首先,由于Chrome浏览器分配给每个tap进程都会有一定的内存最高值,这是操作系统对它的限制,执行10000条数据似乎就使页面处在崩溃的边缘,所以处于这样的运行环境下,可供Javascript支配的内存十分有限,而减少内存消耗,提高打开页面的效率就尤其重要。

      其次,document 即文档对象,HTML的文档document页面是一切的基础,没有它DOM就无从谈起,有了它我们就能通过JavaScript操纵DOM元素。这段代码通过document查找元素,一般来说查找一次就够了,但是这里查找了10000次,这是代码缺点导致的问题,对于性能优化没有概念的人往往会这样写代码。 

    也许有人会说查找元素开销很小,但这里使用了DOM后开销就不一样了,别急,我们先从优化代码开始:  

    <div id="container"></div>    
    <script>        
    let oContainer=document.getElementById('container');        
    for(var count=0;count<10000;count++){
              oContainer.innerHTML+='<span>DOM小测试</span>';        
    }    
    </script>
    

      通过重新定义一个对象,使用document.getElementById(),这样就省去了对元素9999次的      查找。

     那么DOM的开销到底为什么会这么大呢?

      当你看到一个页面时,它是分成两步打开的,这就涉及到一些底层原理。

     1.下载html,css,这是浏览器在渲染页面的第一步。

       这时会形成一个html的DOM树,这样才能实现树的查询。 因为html文件代码是一种一开一     关的结构,使用开关标签  如:, 就是为了形成这样一个DOM树。由于       浏览器本身是由C/C++写出来的,DOM如果要在页面上显示、查询,就必须形成一个tree       的结构, html和文件目录很相似,都是使用tree这样一种数据结构写出来的,所以会先生成     一个DOM树来形成html的结构和层次,body则是根节点,结点之下再挂结点, 用树的形式     能够很好地完成这一点。

    浅谈JavaScript性能优化

       接着是css的解析执行,这是基于DOM树,生成css渲染树CSSOM,因为css有选择器selector,和属性构成一个Render tree,因为树结构执行得很快,所以就可以和html DOM树做匹配。

    2.JavaScript=>Style=>Layout=>Paint=>Composite=>Reflow?=>Repaint?渲染DOM树和CSSOM树JavaScript规则合并DOM树和CSSOM树行程Render Tree  遍历渲染树开始局,计算每个节点的位置大小信息,将Render Tree的每个节点绘制在屏幕上reflow: 元素的几何尺寸发生了改变,需要重新验证并计算渲染树,是渲染树的一部分或者全部发生了变化repaint: 屏幕的一部分重画,不影响整体布局,比如某个CSS的背景色变了,但元素的几何尺寸和位置不变三、页面渲染过程优化.。

    浅谈JavaScript性能优化

    所以当我们写页面的时候,一定要把放在body的最后面,这是优化代码的第一条,我们不需要对这个页面进行操作,但是我们需要尽快地看到静态页面,要把页面显示出来,然后只要HTTP请求把这个html页面发给我们,就会立刻形成DOM树,检查有没有link,src标签,从而生成css渲染树CSSOM。

    总而言之,操作DOM具体的开销成本,说到底是造成浏览器回流reflow和重绘reflow,从而消耗CPU资源,而这个过程如果重复10000次,消耗的内存自然会很大。

    JavaScript是一个极其差性能的家伙:

    1.JavaScript和Java比,性能相对较慢,因为Java是底层的内存操作级别语言,JavaScript只有它1/5的性能速度,所以和php,python等性能速度更快的脚本语言比拼是不现实的,但JavaScript的应用场景是目前唯一可以做前端的语言,虽说Go语言也初现端倪,但暂时还是无法和JavaScript竞争,而且JavaScript通过node可以做后端,移动端。 

    2.JavaScript因为浏览器的缘故,在某种意义上来说是一个第三者,而DOM树和css渲染树是一对的,从而快速地把静态页面显示出来,这是第一要务。

    编写一个监听事件:

    document.addEventListener('DOMContentLoaded',()=>{            
    console.log('DomContentLoaded');        
    },false);       
    window.addEventListener('load',()=>{            
    console.log('loaded');        
    },false)
    

    我们看看输出顺序:

    浅谈JavaScript性能优化

    很显然,DomContentLoaded先执行,而loaded后执行。产生这种状况是由于当“document.addEventListener('DOMContentLoaded',()=>{” 执行的时候,DOM和CSS结合完成了,显示静态页面,早一点输出;而当“window.addEventListener('load',()=>{”执行的时候,需要加载各种资源,如js,img,src...,要花大量的时间,所以运行输出较慢。

    JS是第三者,当DOM树和css渲染树结合在一起时,它还能操作DOM,还能操作样式,它的使命就是操作动态DOM,实现动态页面,所以document.getElementById('')就会有巨大的开销,这个开销是来自从JS(语言世界)-> html+css DOM树世界,这一点是别的语言没有的,而DOM小测试中document.getElementById('')在这两个世界来回穿梭了10000次,开销自然是非常大的。

    那么,优化后的DOM小测试还有优化的空间吗?

    有的,而且关键就在这句代码:

    oContainer.innerHTML+='<span>DOM小测试</span>'
    

    因为document读入消耗很大,innerHTML写入的消耗更大,所以据此进行代码优化:

     let oContainer=document.getElementById('container');//read let content='' for(var count=0;count<10000;count++){ content+='<span>我是一个小测试</span>';//js java c++ //read} oContainer      .innerHTML+=content;
    

    这10000次的操作我们是省不了的,所以声明一个content事件,让这10000次在这一个事件中做,做一个内存级别的字符串拼接,这是和JAVA,C++一样的语言级别的开销,因为只在JS的世界执行,所以这会执行的很快。

    毕竟现在网站的页面都很大,像这样优化代码是很必要的,我们要理解JS(语言世界)和 html+css DOM树世界是两个世界,所以当我们遇到操作DOM树的地方,停下来一下,分析一下能不能优化一下,比如开始JS的时候,查找元素尽量一开始就查找完,再引用它,不要每次都去查找再引用,这样会导致第一,重复了代码;第二,性能很差。


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

    常见问题FAQ

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

    发表评论

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

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

    联系作者

    请选择支付方式

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