zoukankan      html  css  js  c++  java
  • 高性能javascript笔记

        ----------------------------------------------------------- 第一章 加载和执行 -------------------------------------
    1.脚本位置
        浏览器在遇到<script>标签时会等待脚本下载完并执行完才会继续渲染页面
            因为js代码有可能会改变dom结构,所以需要等待js的执行完成
            遇到<script>标签 -> 下载脚本 -> 执行脚本 -> 继续渲染
            旧浏览器:逐个下载,逐个执行
            新浏览器:并发下载,顺序逐个执行
        so: 脚本尽量放在靠近</body>的底部
            尽可能合并脚本(下载一个比下载多个快)
    2.延迟的脚本
        defer:立刻下载,等到onload事件被触发前才执行(仅IE4.0+和Firefox3.5+支持)
        动态创建<script>节点:添加到页面时开始下载,下载完成立刻执行
            * 下载完成的事件:readystatechange(IE)、onload(其他浏览器)
        XHR脚本注入:XMLHttpRequest来获取js文件内容,再动态创建<script>节点
            * 必须处于相同域,不适用大型Web应用
    3.推荐的方式
        先添加动态加载所需的代码,然后加载其他代码:
            <script type="text/javascript" src = "loader.js"></script>
            <script type="text/javascript">
                loadScript("the-rest.js"),function(){
                    Application.init();
                }
            </script>
            放置</body>闭合标签前,保证DOM结构已经创建完毕,无需其他的时间,例如window.onload来检测页面是否准备好
    4.类库
        LazyLoad.js:
            <script type="text/javascript" src = "lazyload-min.js"></script>
            <script type="text/javascript">
                LazyLoad.js(["first.js","second.js"]),function(){
                    Application.init();
                }
            </script>
        lab.js:
            <script type="text/javascript" src = "lab.js"></script>
            <script type="text/javascript">
                $LAB.script("first.js").wait()    // 如果需要按序执行则需要加上wait()
                    .script("second.js")
                    .wait(function(){
                            Application.init();
                    });
            </script>
       
    --------------------------------第二章 数据访问---------------------------------------
    1.作用域链和标识符解析
        内部属性[[Scope]] --- 作用域链  --- 0 --- 活动对象([[Scope]]属性中所包含的对象,即函数范围内的变量)
                                        --- 1 --- 全局对象(this, window, document 等等全局变量)
    2.so 尽量把链深处的变量存储到局部变量里,介以提升性能
        * 采用优化过的js引擎不存在这种问题,老版的IE、Firefox和Safari都有问题

    3.改变作用域链:
            with(document){...}    //with把document推进了作用域链的第一层,但是导致访问局部变量路径变远了,所以不推荐
            try{}catch(ex){}    //catch里面把异常对象推入了作用域链的头部

    4.访问对象也一样,首先在实例中查找,然后再去原型链中查找
        so 如果需要访问多次,那么缓存对象属性可以提升性能
       
    --------------------------------第三章 DOM编程---------------------------------------
    1.尽量少访问DOM,把运算留在ECMAScript这一端处理

    2.innerHTML属性和类似document.createElement()、document.createTextNode()的原生DOM方法性能差不多

    3.cloneNode()比createElement要稍快一点

    4.HTML集合
        document.getElementsByName();
        document.getElementsByClassName();
        document.getElementsByTagName();
        HTML集合是动态的,类数组,提供一个length属性
        * 访问length属性时会重新执行一次查询的过程
        so,缓存length属性很有必要
       
    5.只返回元素节点
        children                    childNodes
        childElementCount            childNodes.length
        firstElementChild            firstChild
        lastElementChild            lastChild
        nextElementSibling            nextSibling
        previousElementSibling        previousSibling
       
    6.选择器API
        原生DOM方法:querySelectorAll();
       
    7.重绘与重排
        构建DOM树与渲染树 --- 绘制页面元素
        重排:
            添加、删除DOM元素
            元素位置改变
            元素尺寸改变
            内容改变(例如文本改变、图片被另外一个不同尺寸的图片替代)
            页面渲染器初始化
            浏览器窗口尺寸改变
        浏览器通过队列化修改并批量执行来优化重排过程,但以下属性会强制刷新队列:
        offsetTop, offsetLeft, offsetWidth, offsetHeight
        scroll...
        client...
        getComputedStyle()(currentStyle in IE)
        以上属性需要返回最新的布局信息,所以浏览器需要执行队列中的"待处理变化"并触发重排以返回正确的值
        so 以上属性尽量少使用,并且使用这些属性的位置应该在修改布局信息的后面,中间的话会导致多次重排

    8.最小化重绘和重排
        ·合并多次所有的改变一次处理
        ·批量修改DOM
            脱离文档流
            应用多重改变
            带回文档
        三种方式:隐藏元素 --- 修改 --- 重新显示
                    使用文档片段(document fragment)
                    拷贝 --- 修改拷贝 --- 替换原始(replaceChild(new, old))
       
    9.缓存布局信息

    10.让元素脱离动画流
        绝对定位页面上的动画元素,将其脱离文档流
        让元素动起来,只重绘了该元素,会临时覆盖部分页面
        动画结束时恢复定位,只下移一次文档的其他元素

    11.元素很多时应避免使用:hover这个CSS伪选择器

    12.事件委托
        只绑定最外围的元素点击事件,判断来源是否是目标

    --------------------------------第四章 算法和流程控制---------------------------------------
    1.for-in循环的性能只有其他循环的1/7,
        so 尽量不要使用for-in来遍历对象的属性名

    2.少量条件用if-else, 大量条件用switch-case

    3.列表查找比循环查找要快
        so, 数据放置一个Array中, 通过位置来查找
       
    4.尽量减少循环

    5.存在重复的计算结果时,可以使用缓存

    --------------------------------第五章 字符串和正则表达式---------------------------------------
    1.字符串连接
        把基础字符串及放置左边可以提升性能
        * 因为除IE外,其他浏览器会尝试为左侧的字符串分配更多的内存,然后简单地将第二个字符串拷贝至它的末尾
       
    2.Array.prototype.join();
        String.prototype.concat();    //concat比普通的+和+=以及join慢一点

    3.正则表达式的编译很快,只需要注意别在循环中重复编译正则表达式就行
        while(/regex1/.test(str1))
       
    4.只是检测位置不适用正则表达式
        例如检测是否以;结尾:
            /;$/ --- str.charAt(str.length-1)== ";";
        其他函数有slice、substr、substring、indexOf和lastIndexOf
       
    5.去除首尾空格
        用两个子表达式综合效率要高一些,尤其是在处理长字符串时
        str.replace(/^s+/,"").replace(/s+$/,"");
        * 其他有一次性处理完的,但多少有各方面的性能问题
            比方说/^s+|s+$/,每个字符串都会去匹配这两个分支条件

    --------------------------------第六章 快速响应的用户界面---------------------------------------
    1.js的执行不应超过100毫秒(用户体验中能忍受的页面阻塞时间最大值)

    2.定时器的推荐最小值为25毫秒
        * windows系统的最小识别为15毫秒,设置一个小于15毫秒的定时值,IE会锁定
        * 在小于10毫秒时,各浏览器各系统均会有不同的表现
       
    3.可以通过定时器来依次执行多个任务
        * 将一个任务分割成多个任务,用定时器来执行
       
    4.Web Workers
        Worker没有绑定UI线程,适用于纯数据处理,与网页代码通过事件接口进行通信
        网页代码:
            var worker = new Worker("code.js");
            worker.onmessage = faunction(event){
                // ...
            }
            worker.postMessage("Thyiad");
        worker代码(code.js):
            importScripts("file1.js", "file2.js");
            self.onmessage = function(event){
                self.postMessage("Hello, " + event.data + "!");
            }
           
    --------------------------------第七章 AJAX---------------------------------------
    1.常用的三种技术是:XHR、动态脚本注入和multipart XHR

    2.XHR
        readyState的值
            3    正在与服务器交互
            4    整个响应已接收完毕,可进行操作
        * GET常用来请求数据,POST则用来发送数据
            一个GET请求只会发送一次数据包,而一个POST请求会发送两次数据包(一个装载头一个装载正文)
            应该在参数接近或超过2048个字符时,才应该使用POST获取数据,因为IE限制URL长度
        * 不能跨域请求数据

    3.动态脚本注入
        动态创建一个script元素,设置src属性为不同域的URL
        * 返回的响应消息必须是可执行的JavaScript代码
       
    4.Multipart XHR
        一次请求多个资源,从readyState值为3时开始设定一个定时器监听处理数据(需要自己定义数据格式并处理)
        * 这种方式资源不会被缓存
        * IE6、7不支持readyState为3的状态和data:URL

    5.Beancons - 信标
        通过创建一个Image,设定src来回传数据
            var beacon = new Image();
            beacon.src=url+'?'+params.join('&');
            beancon.onload = function(){    // 通过监听image的load事件来处理简单返回时间
                if(this.width === 1){        // 如果不需要返回数据,那么响应中应该发送一个 204 No Content 状态码(即:不带消息正文)
                }                            // 以阻止客户端继续等待永远不会到来的消息正文
                else{}
            }
           
    6.数据格式
        XML        不推荐,数据量大解析又慢
        JSON    推荐,数据轻便解析又快
        JSON-P    返回的文本作为js代码直接执行(用eval直接调用)
        HTML    不推荐,既缓慢又臃肿
        自定义    同JSON,适用的情景下速度还会比JSON更快点
       
    7.缓存数据
        用GET请求数据、响应中发送 Expires 头信息:Expires: Mon, 28 Jul 2015 23:30:00 GMT    // 告诉浏览器缓存此响应到7月
        本地数据存储:使用对象的属性存储缓存(键存url,值存返回数据)
        * 本地存储最适用移动设备,大多移动设备的浏览器都很小或没有缓存
       
    --------------------------------第八章 编程实践---------------------------------------
    1.避免双重求值
        尽量不使用eval和Function构造函数,以避免双重求值带来的性能消耗
        同样的,应该给setTimeout()和setInterval()传入函数而不是字符串作为参数
       
    2.使用直接量创建对象和数组 - 效率更高

    3.不要重复工作
        当需要检测浏览器时,可使用延迟加载或条件预加载
        延迟加载:
            function addHandler(target, eventType, handler){
                if(target.addEventListener){
                    addHandler = function(target, eventType, handler){
                        target.addEventListener(eventType, handler, false);
                    }
                }
                else{
                    addHandler = function(target, eventType, handler){
                        target.attachEvent("on"+eventType, handler);
                    }
                }
               
                addHandler(target, eventType, handler);
            }
        条件预加载:
            var addHandler = document.body.addEventListener ?
                function(target, eventType, handler){
                        target.addEventListener(eventType, handler, false);
                    } :
                function(target, eventType, handler){
                        target.attachEvent("on"+eventType, handler);
                    };

    4.使用速度快的部分
        位操作
            toString()方法把数字转换为二进制形式的字符串:
                var num = 25;
                alert(num.toString(2));        //"11001"
            是否为2的整数:
                var num = 25;
                if(num & 1){    // 奇数&1 => 1
                }
                else{}            // 偶数
            位掩码:
                var OPTION_A = 1, OPTION_B = 2, OPTION_C = 4, OPTION_D = 8, OPTION_E = 16;
                var options = OPTION_A | OPTION_C | OPTION_D;
                if(options & OPTION_A){    //选项A是否在列表中
                    // ...
                }
               
    5.原生方法
        尽量使用原生方法,比如数学计算(Math)和CSS选择器(querySelector()、querySelectorAll())
       
    --------------------------------第九章 构建并部署高性能JavaScript应用---------------------------------------
    1.Apache Ant

    2.合并多个JavaScript文件

    3.预处理JavaScript文件
        在js代码中添加宏定义(#define, #undef)和条件编译(#if, #ifdef, #ifndef)

    4.JavaScript压缩
        JSMin                http://www.crockford.com/javascript/jsmin.html
        YUI Compressor        http://developer.yahoo.com/yui/compressor
        Closure Compiler    http://code.google.com/closure/compiler/
        Packer                http://dean.edwards.name/packer/

    5.JavaScript的HTTP压缩
        Accept-Encoding HTTP头:值为gzip、compress、deflate和identity
            服务器会选择最合适的编码方法,通过Content-Encoding HTTP头来告知浏览器
           
    6.缓存JavaScript文件
        * Expires HTTP 响应头
        * 客户端存储机制(js自己控制)
        * HTML5 离线应用缓存(manifest属性,mime type为text/cache-manifest)
       
    7.处理缓存问题
        推荐使用时间戳后缀
       
    8.CDN
       
    --------------------------------第十章 工具---------------------------------------
    1.原生分析
        new Date();    //通过Date相减
       
    2.YUI Profiler
       
    3.FireBug

    4.Console API
        profile()、profileEnd()
            console.profile("regexTest");
            regexTest();
            console.profileEnd();
            * profileEnd()会阻塞后续执行,所以可以将profileEnd()调用封装在setTimeout中
           
    5.Page Speed
        对如何重构进行分析建议,比如哪些脚本在load之前没有用到过,可以延迟加载
        * FireBug插件
       
    6.Fiddler
        HTTP调试代理工具,整个网络过程的Timeline进行分析,哪块占用时间多需要优化
       
    7.YSlow
        分析后的优化建议工具 
        * FireBug插件
           
    8.dynatrace Ajax Edition
        同Fiddler的作用,可以监控整个过程的时间,更能深入到特定的事件

  • 相关阅读:
    @codeforces
    @codeforces
    @hdu
    @hdu
    @bzoj
    @bzoj
    @topcoder
    推荐系统主题相关资料
    Python统计百分比及排序
    如何发布及部署asp.net网站
  • 原文地址:https://www.cnblogs.com/thyong/p/5274742.html
Copyright © 2011-2022 走看看