zoukankan      html  css  js  c++  java
  • JavaScript高级程序设计学习笔记--高级技巧


    惰性载入函数

    因为浏览器之间行为的差异,多数JavaScript代码包含了大量的if语句,将执行引导到正确的代码中,看看下面来自上一章的createXHR()函数。

            function createXHR(){
                if (typeof XMLHttpRequest != "undefined"){
                    return new XMLHttpRequest();
                } else if (typeof ActiveXObject != "undefined"){
                    if (typeof arguments.callee.activeXString != "string"){
                        var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0",
                                        "MSXML2.XMLHttp"],
                            i, len;
                
                        for (i=0,len=versions.length; i < len; i++){
                            try {
                                new ActiveXObject(versions[i]);
                                arguments.callee.activeXString = versions[i];
                                break;
                            } catch (ex){
                                //skip
                            }
                        }
                    }
                
                    return new ActiveXObject(arguments.callee.activeXString);
                } else {
                    throw new Error("No XHR object available.");
                }
            }

    每次调用createXHR()的时候,它都要对浏览器所支持的能力仔细检查。每次调用该函数都是这样,即使每次调用时分支的结果不变:浏览器内置XHR,那么它就一直支持了,那么
    这种测试就变得没必要了。即使只有一个If语句的代码,也肯定要比没有If语句慢,所以如果If语句不必要每次执行,那么代码可以运行地更快一些。解决方案就是称之为惰性载入
    的技巧。
    惰性载入表示函数执行的分支仅会发生一次。有两种实现惰性载入的方式。第一种就是在函数被调用时再处理函数,在第一次调用的过程中,该函数会被覆盖为另外一个按合适方式
    执行的函数,这样第二次再调用的时候就不用再经过执行的分支了。

            function createXHR(){
                if (typeof XMLHttpRequest != "undefined"){
                    createXHR = function(){
                        return new XMLHttpRequest();
                    };
                } else if (typeof ActiveXObject != "undefined"){
                    createXHR = function(){                    
                        if (typeof arguments.callee.activeXString != "string"){
                            var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0",
                                            "MSXML2.XMLHttp"],
                                i, len;
                    
                            for (i=0,len=versions.length; i < len; i++){
                                try {
                                    new ActiveXObject(versions[i]);
                                    arguments.callee.activeXString = versions[i];
                                } catch (ex){
                                    //skip
                                }
                            }
                        }
                    
                        return new ActiveXObject(arguments.callee.activeXString);
                    };
                } else {
                    createXHR = function(){
                        throw new Error("No XHR object available.");
                    };
                }
                
                return createXHR();
            }
            
            var xhr1 = createXHR();
            var xhr2 = createXHR();

    第二种实现惰性载入的方式是在声明函数时就指定适当的函数。这样,第一次调用函数时就不会损失性能了,而在代码首次加载时会损失一点性能。

            var createXHR = (function(){
                if (typeof XMLHttpRequest != "undefined"){
                    return function(){
                        return new XMLHttpRequest();
                    };
                } else if (typeof ActiveXObject != "undefined"){
                    return function(){                    
                        if (typeof arguments.callee.activeXString != "string"){
                            var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0",
                                            "MSXML2.XMLHttp"],
                                i, len;
                    
                            for (i=0,len=versions.length; i < len; i++){
                                try {
                                    new ActiveXObject(versions[i]);
                                    arguments.callee.activeXString = versions[i];
                                    break;
                                } catch (ex){
                                    //skip
                                }
                            }
                        }
                    
                        return new ActiveXObject(arguments.callee.activeXString);
                    };
                } else {
                    return function(){
                        throw new Error("No XHR object available.");
                    };
                }
            })();
            
            var xhr1 = createXHR();
            var xhr2 = createXHR();

    重复的定时器

            setTimeout(function(){
            
               var div = document.getElementById("myDiv"),
                   left = parseInt(div.style.left) + 5;
               div.style.left = left + "px";
            
               if (left < 200){
                   setTimeout(arguments.callee, 50);
               }
            
            }, 50);

    函数节流

    函数节流背后的基本思想是指,某些代码不可以在没有间断的情况下连续重复执行。第一次调用函数创建一个定时器,在指定的时间间隔之后运动代码。当第二次调用该函数时,
    它会清除前一次的定时器并设置另一个。如果前一个定时器已经执行过了,这个操作就没有任何意义。然而,如果前一个定时器尚未执行,其实就是将其替换为一个新的定时器。
    目的是只有在执行函数请求停止了一段时间 之后才执行。以下是该模式的基本形式:

     var processor={
       timeoutId:null,
        //实际进行处理的方法
       performProcessing:function(){
         //实际执行的代码
       },
       process:function(){
        clearTimeout(this.timeoutId);
        
        var that=this;
        this.timeoutId=setTimeout(function(){
          that.performProcessing();
        },100
       }
     };

    当调用了process(),第一步是清除存好的timeoutId,来阻止之前的调用被执行。然后,创建一个新定时器调用performProcessing()。由于setTimeout()中用到的函数环境总是
    window,所以有必要保存this的引用以方便以后使用。
    时间间隔设为了100ms,这表示最后一次调用process()之后至少100ms后才会调用performProcessing()。所以如果100ms之间内调用了process()共20次,performanceProcessing()
    仍只会被调用一次。
    这个模式可以用throttle()函数来简化,这个函数可以自动进行定时器的设置和消除,如下例所示:

             function throttle(method, scope) {
                clearTimeout(method.tId);
                method.tId= setTimeout(function(){
                    method.call(scope);
                }, 100);
            }
        
            function resizeDiv(){
                var div = document.getElementById("myDiv");
                div.style.height = div.offsetWidth + "px";
            }
            
            window.onresize = function(){
                throttle(resizeDiv);
            };
  • 相关阅读:
    [AGC005D] ~K Perm Counting
    [国家集训队]middle
    CF842D Vitya and Strange Lesson
    浅谈脚本化css(三)之方块运动函数
    浅谈脚本化css(二)
    浅谈脚本化css(一)
    滚动条详解及制作(三)
    滚动条详解及制作(二)
    滚动条详解及制作(一)
    javascript定时器详解
  • 原文地址:https://www.cnblogs.com/Gyoung/p/3834876.html
Copyright © 2011-2022 走看看