zoukankan      html  css  js  c++  java
  • javascript 的性能问题

    1) 控制作用域

      对变量的符号的查询总是沿着作用域链, 从局部作用域开始查询, 如果查到了就停止, 否则继续查询外层作用域 ....一直到全局作用域为止。

      所以: 对全局变量的访问时间 > 对局部变量的访问时间。因此要局部变量缓存全局对象可以提高性能。

    // Bad example:
    // 对于全局对象 document的访问, 每次访问document都会进行作用域链查找, 一直查找到全局作用域, 降低了性能.
    function updateUI_Bad() {
      var imgs = document.getElementsByTagName("img");
        for (var i = 0, len = imgs.length; i < len; i++) {
          imgs[i].title = document.title + " image " + i;
        }
      var msg = document.getElementById("msg");
      msg.innerHTML = "Update complete.";
    }
    // Good example:
    // 把全局对象document存在本地. 除了第一次, 以后使用doc, 减少了作用域链的访问时间.
    function udpateUI_Good() {
      var doc = document;
      var imgs = doc.getElementsByTagName("img");
      for (var i = 0, len = imgs.length; i < len; i++) {
        imgs[i].title = doc.title + " image " + i;
      }
      var msg = doc.getElementById("msg");
      msg.innerHTML = "Update complete."; 
    }

    2) 避免不必要的属性查找

      一旦多次用到的对象属性, 应该将其存储在局部变量中。第一次访问该值复杂度是O(n), 以后访问的复杂度是O(1).

      不要console(a.b.c); console(a.b.c); console(a.b.c); console(a.b.c); console(a.b.c);

      而要  var c = a.b.c; console(c); console(c); console(c); console(c); console(c);

    // 访问变量, 数字的复杂度是 O(1)
    var value = 5;      // O(1)
    var sum = 10 + value;  // O(1)
    // 访问数组中的元素的复杂度也是O(1) var values = [5, 10];       // O(1) var sum = values[0] + values[1];// O(1)

    // 访问对象上的属性的复杂度是 O(n)
    // Bad example:
    var query = window.location.href.substring(window.location.href.indexOf("?"));
    // 查找 "substring" (window.location.href.substring) 有3次查找
    // 查找 "indexOf"   (window.location.href.indexOf)   有3次查找
    // Good example:
    var url = window.location.href;
    var query = url.substring(url.indexOf("?"));
    // 只有4次属性查找

    3) 避免双重解释

      如果代码包含在字符串中, javascript 代码运行的同时必须启动一个新的解析器来解析新的代码(写成字符串形式的代码)。而启动一个新的解析器会产生开销, 影响效率。

    // Bad
    eval("alert('Hello world!')");
    // Good
    alert('Hello world!');
    // Bad var sayHi = new Function("alert('Hello world!')"); // Good var sayHi = function() {   alert('Hello world!'); };
    // Bad setTimeout("alert('Hello world!')", 5000); // Good setTimeout(function() {   alert('Hello world!'); }, 5000)

    4) 减少 DOM 更新次数

      JS 的 DOM 操作开销非常大 : 每次个更改(插入 or 删除), 浏览器都要重新计算各种元素的size, 从而需要重新渲染页面的一部分甚至整个页面,  所以DOM更新次数越多, 开销越大
    // Bad example
    // 添加每个item 需要 2 次 DOM 更新 : 一个添加 <li> 元素, 两一个给 <li> 添加文本节点.
    // 为 list 添加 10 个元素, 共需要 20 次 DOM 更新.
    var list = document.getElementById("myList");
    for (var i = 0; i < 10; i++) {
      var item = document.createElement("li");
      list.appendChild(item);
      item.appendChild(document.createTextNode("Item " + i));
    }
    // Good example // 使用 DocumentFragment, 把 <li> 添加到 DocumentFragment 上, 最后一次性地把 DocumentFragment 更新到 <list> 上 var list = document.getElementById("myList"), fragment = document.createDocumentFragment(); for (var i = 0; i < 10; i++) {   var item = document.createElement("li");   item.appendChild(document.createTextNode("Item " + i));   fragment.appendChild(item); } list.appendChild(fragment);

    5) innerHTML

      innerHTML 速度  > createElement() + appendChild()。

      因为 后台会为 innerHTML 创建一个 HTML 解析器, 使用内部的 DOM 调用创建 DOM 结构, 而不是基于 JS 的 DOM 调用。内部方法是编译好的二进制调用而不是解析调用, 所以速度快。

      使用 innerHTML 时需要注意最小化对 innerHTML 的调用:

    // Bad example
    for (var i = 0; i < 10) {
      list.innerHTML += "<li>Item " + i + "</li>"; // 这里每一次运算, 都会产生一次 DOM 操作:
                                // 1) innerHTML += "<li>Item "; 2) innerHTML += i; 3) innerHTML += "</li>";
    }
    // Good example for (var i = 0; i < 10) {   var item = "<li>Item " + i + "</li>";   list.innerHTML += item; }

    6) 注意 NodeList

      操作返回 NodeList 对象的操作包括:  getElementsByTagName(), 获取元素的 childNodes 属性, 获取元素的 attributes 属性, 访问特殊集合: document.form / document.images。

      访问 DOCUMENT 的 元素 list 开销很大, 应该尽量减少对 元素 list的访问。

    //
    var imageList = document.getElementsByTagName("img");    // imageList : NodeList
    // Good example
    for (var i = 0, len = imageList.length; i < len; i++) {  // 使用 len 保存 imageList.length, 而不是每次都访问 imageList.length.
      var image = imageList[i];                 // 使用 image 保持当前的 imageList[i], 而不是每次都访问 imageList[i].
    }

      

  • 相关阅读:
    centos下如何关闭xdebug扩展
    xdebug调试的原理
    取值再拼接跳转链接
    描点返回-动画
    比较旧的写法:验证车牌、手机号、电话、qq等
    jQuery实现ie浏览器兼容placeholder效果
    CSS3的REM设置字体大小
    整理前端问题
    css3 hover效果
    ie7 a标签强制不换行兼容问题
  • 原文地址:https://www.cnblogs.com/happylong/p/4328463.html
Copyright © 2011-2022 走看看