zoukankan      html  css  js  c++  java
  • <高性能JavaScript>笔记 [1~3]

    <高性能JavaScript>这是一本很好的书,主要讨论实际js开发时要注意的性能问题.

    也算是一本JS的进阶读物,如果要看此书,建议先看<JavaScript权威指南>


    一:加载和执行


    主要讲述了如何更高效的载入JavaScript脚本文件,解决浏览器的阻塞问题.

    其中最简单的解决方法就是把导入的js文件的标签写在 </body> 前,而且不需要使用 onload 事件.
    尽量把js文件进行压缩和合并,因为每次加载一个外链js文件都需要发送一次http请求,这样会增加性能的消耗.

    另外,每一个 <script> 标签初始下载时都会堵塞页面渲染,这不仅针对外链脚本,内嵌脚本也有同样的情况,每遇到一个 <script> 标签就会因执行脚本而导致一定的延时,所以减少<script> 标签能改善页面的总体性能.
    当把内嵌脚本放在引用外联样式表的 <link> 标签之后会导致页面堵塞去等待样式表的下载,这样做是为了确保内嵌脚本在执行时能获得最精准的样式信息,因此不建议把内嵌脚本紧跟在<link> 标签之后.

    那什么是无阻塞脚本呢?
    window 对象的 onload 事件触发后才下载脚本,就是所谓的无堵塞脚本.因为这个时候下载脚本不会影响页面的下载和渲染.
    解决方法有:
    + 延迟脚本(Deferred Script) - 使用 <script> defer 属性(仅适用于IE和Firefox3.5+);
    + 动态脚本元素(Dynamic Script Elements) - 使用动态创建的 <script> 元素来下载并执行代码;
    + XMLHttpRequest脚本注入(XMLHttpRequest Script Injection) - 使用 XMLHttpRequest 对象下载js代码并注入页面;

    最后,
    还介绍了YUI3,LazyLoad,LABjs等库来实现无阻塞脚本.



    二:数据访问

    - 访问直接量和局部变量的速度最快,相反,访问数组元素的对象成员相对较慢;

    - 由于局部变量存在于作用域链的起始位置,因此访问局部变量比访问跨作用域变量更快.变量在作用域链中的位置越深,访问所需时间就越长.由于全局变量总处在作用域链的最末端,因此访问速度也是最慢的;

    - 避免使用 with 语句,因为它会改变运行期上下文作用域链.同样, try-catch 语句中的 catch 也有同样的影响,因此也要小心使用;

    - 嵌套的对象成员会明显影响性能,尽量少用. 如: location.href 比 window.location.href 要快;

    - 属性或方法在原型链中的位置越深,访问它的速度也越慢;

    - 通常来说,你可以通过把常用的对象成员,数组元素,跨域变量保存在局部变量中来改善JavaScript的性能,因为局部变量访问速度更快. 如: var div = document.getElementById("div");


    这章用了很多UML图来解释JavaScript的数据访问,很具体形象.



    三:DOM访问与修改

    浏览器中通常会把DOM和JavaScript独立实现,分为两个不同的库.
    因此访问DOM需要巨大的性能开销.
    尽量避免DOM的访问次数,是提高性能的重要环节.
    例如:多次访问的DOM节点可以通过局部变量来存储.

    另外,要小心处理HTML集合.
    以下方法和属性均返回一个HTML集合:
    document.getElementByName()
    document.getElementsByClassName()
    document.getElementsByTagName()
    document.all
    document.images
    document.links
    document.forms
    document.forms[0].elements

    所谓的的HTML集合,是动态返回对应的HTML对象集合.
    每一次调用以上方法和属性,都会重复一次查询元素的过程,开销十分大.
    建议copy到一个数组对象中再进行操作.

    许多现代浏览器均提供一些API来操作元素节点.
     
    属性名
    被替换的属性
    children
    childNodes
    childElementCount
    childNodes.length
    firstElementChild
    firstChild
    lastElementChild
    lastChild
    nextElementSibling
    nextSibling
    previousElementSibling
    previousSibling
     
    以上属性Firefox 3.5+, Safari 4+, Chrome 2+, Opera 9.62+ 均支持.
    但IE6,7,8只支持children属性.

    还可以使用CSS选择器来获取特定元素对象.
    最新的浏览器都提供了一个querySelectorAll()的方法.
    例如: var elements = document.querySelectorAll("#menu a");
    不过该方法返回的对象是一个NodeList的类数组对象,并不是HTML集合.
    所以并不会重复查询元素.
    IE 8+, Firefox 3.5+, Safari 3.1+, Chrome 1+, Opera 10+ 均支持该属性.
    querySelector() 用来获取第一个匹配的节点.


    尽量减少渲染树的强制刷新(关于DOM树和渲染树,请自行Google或查阅该书)
    以下方法会导致渲染树的强制刷新:
    offsetTop, offsetLeft, offsetWidth, offsetHeight
    scrollTop, scrollLeft, scrollWidth, scrollHeight
    clientTop, clientLeft, clientWidth, clientHeight
    getComputedStyle() (currentStyle in IE)
    以上属性和方法需要返回最新的布局信息,因为要强制渲染列队中的渲染树修改项.
    在修改样式的过程中,最好避免使用上面列出的属性.

    对于css样式的多次操作,可以通过cssText进行合并:
    element.style.cssText = "border-left: 1px; padding: 5px;"
    但此方法是直接覆盖已有的style样式,如果要追加样式:
    element.style.cssText += "margin: 5px;"
    当然,也可以通过修改class名称避免多次强制刷新

    需要批量修改DOM时,可以通过通过下面的方法优化,借此减少强制刷新的次数:
    +隐藏元素,应用修改,重新显示;
    +使用文档片断进行构建子树,然后插入文档; (建议使用此方法 createDocumentFragment() )
    +将原始元素拷贝到一个脱离文档的节点,修改副本在进行替换;

    还要避免页面大部分元素的重排,可以让动画元素使用绝对定位脱离文档流.
    善于利用时间委托,也是提高性能的好办法.







  • 相关阅读:
    231. Power of Two
    204. Count Primes
    205. Isomorphic Strings
    203. Remove Linked List Elements
    179. Largest Number
    922. Sort Array By Parity II
    350. Intersection of Two Arrays II
    242. Valid Anagram
    164. Maximum Gap
    147. Insertion Sort List
  • 原文地址:https://www.cnblogs.com/maplejan/p/2731951.html
Copyright © 2011-2022 走看看