增强JavaScript性能(略写)

  1. 当浏览器遇到<script>标签时,在大多数情况下,它会停止渲染页面,直到完成对该脚本的读取和解析。所以,把所有能够移动的<script>标签挪至HTML的</body>标签之前
  2. 将JavaScript文件编制成GZip编码传输。(详细资料见本书P85)。
  3. 缩编、混淆和编译
    1. 缩编是将JavaScript代码中所有的空格个换行符进行移除,以产出更小体积的代码文件,但是处理后的代码仍保留着由开发者编写的完全相同的语句。
    2. 混淆是一种更高级的代码优化方法,它会着眼于变量和函数名称,并找出哪些是可全局性访问,哪些限定在特定的作用域之内。
    3. 编译时一种更先进的处理方法,它会全面地对代码进行分析,并对代码中的语句进行简化、缩减、整合,生成有着相同行为的另一语句。与缩编和混淆相结合是,这是产生最小体积文件的最有效的方法。
  4. 优化文档对象的操作

    1. 以变量保存对DOM元素的引用以便后续使用
      var header = document.getElementById("header"),
      nav = document.getElementById("nav");
    2. 通过对单独父元素的引用来访问其子DOM元素,不要直接获取对整个页面的引用并使用它,因为所需的内存占用的是整个DOM树,再加上JavaScript要深入该树查找需要访问的元素所花费的时间,这对应用程序将产生负面的性能影响。
      var wrapper = document.getElementById("wrapper"),
      header = wrapper.getElementsByTagName("div")[0],
      nav = wrapper.getElementsByTagName("div")[1];
    3. 对新建元素实施DOM修改操作后才将其添加至当前实时页面
      var list = document.createElement("ul"),
      listItem = document.createElement("li");
      //先在JavaScript中尽可能地实施所有的DOM操作
      listItem.innerHTML = "I am a list item";
      list.appendChild(listItem);
      //
      document.body.appendChild(list);
    4. 复制已经存在的元素以提高性能
      var list1 = document.createElement("ul"),
      list2;
      list1.className = "list";
      list2 = list1.cloneNode(true);
    5. 应用css类至DOM元素以减少浏览器重排
      var nav = document.getElementById("nav");
      nav.style.backgroundColor = "#000";//在浏览器中引发一次重排
      nav.style.color = "#fff";//引发一次重排
      ····

      正确做法应为:
      nav.className = "selected";
      or
      nav.style.display = "none";
      nav.style.backgroundColor = "#000";
      ···
      nav.style.display = "block";
    6. 事件委托至父元素——DOM事件会从其首次被触发的元素起开始冒泡,一直到文档结构的最顶端。

// 获取对列表元素的引用,此列表包含我们想要为其指派事件处理函数的所有链接
var list = document.getElementById("list");
    // 定义一个函数,当链接或链接中的某个元素被执行时(点击或回车),执行该函数
    function onClick(evt){
        // 利用事件的target属性来获取对所点击的实际元素的引用
        var clickedElem = evt.target,
            tagNameSought = "A";
        //检查所点击的元素是否为我们所要的类型,在这里检查它是否为<a>标签
        if(clickedElem && clickedElem.tagName === tagNameSought){
            window.open(clickedElem.href);
        }
    }

5.提升函数性能(特别针对计算量大的函数)

    // 函数memoize()需要传入一个函数作为参数,返回相同的函数但增加了存储功能
    function memoize(fn){
        return function(){
            var propertyName;

            // 如果这个函数还没有用作记忆的对象属性(该属性为一个对象直接量),则为其添加一个
            fn.storage = fn.storage || {};

            // 在‘storage’对象直接量中建立属性名称,用于保存和重新获取函数的执行结果。属性名称应该基于
            // 传给函数的所有参数而设定,以确保属性名称是唯一的、基于所有可能输入参数组合的
            // 我们借用Array类型的“join”方法,因为“arguments”本身就不是数组类型,它并不包含此方法
            propertyName = Array.prototype.join.call(arguments, "|");

            // 该键值(属性名称)是否存在于用作记忆的对象中
            if(propertyName in fn.storage){
                // 存在,则返回相关联的值以避免再次执行整个函数
                return fn.storage[propertyName];
            } else {
                // 不存在,执行相关函数并将结果保存在用作记忆的对象中
                fn.storage[propertyName] = fn.apply(this, arguments);

                // 返回新保存的值,即函数执行的结果
                return fn.storage[propertyName];
            }
        };
    }
    // 计算的方法函数
    function getFactorial(num){
        var result = 0,
            index = 1;
        for(; index <= num; index++){
            result += index;
        }
        return result;
    }

    var getFactorialMemoized = memoize(getFactorial);
    var time = new Date().getTime();

    console.log(getFactorialMemoized(10000000));
    console.log("first: " + (new Date().getTime() - time));
    time = new Date().getTime();
    console.log(getFactorialMemoized(5000000));
    console.log("second: " + (new Date().getTime() - time));
    time = new Date().getTime();
    console.log(getFactorialMemoized(10000000));
    console.log("third: " + (new Date().getTime() - time));
    time = new Date().getTime();
    console.log(getFactorialMemoized(5000000));
    console.log("forth: " + (new Date().getTime() - time));

猜你喜欢

转载自blog.csdn.net/Char_n/article/details/70245403