• JavaScript优化参考


    最近在为管理系统的网站做点优化,压缩都用了工具,就没太多可以讨论的。

    主要还是代码上的精简和优化。稍微整理一下,顺便做点测试。

    这里先贴上项目中用来替代iFrame的Ajax处理的局部代码,本人比较讨厌用iFrame来实现模块管理(主要是多重嵌套,存在一些刷屏时候白屏、脚本对象不一致、缓存数据问题等等,还有一些是对象引用丢失或者被重定向的情况)。

    这里引入的是jQuery1.8.3.js的版本库

    var ie = (function () {
      // ie10-6
      var ua = navigator.userAgent;
      return ua && /MSIE/.test(ua) ? Number(ua.match(/MSIEs+([^.]*)/) [1])  : 0;
    }());
    var ajaxHtml = function (url, data0, target) {
      var flag = ie > 8 || !/MSIE/.test(ua);
      // ie9+ 和其他主流浏览器
      var getByTagName = function (data, name1, name2, attr) {
        // 手写的脚本代码,用来处理传回的HTML字符串(IE9+和主流浏览器支持直接解析成HTMLDocument对象)
        if (!data || !name1 || !name2) return 0;
        var s = 0,
        e,
        result = [
        ],
        _dom,
        _val;
        while ((s = data.indexOf(name1, s)) > - 1) {
          e = data.indexOf(name2, s);
          _dom = data.substring(s, e);
          if (attr) {
            _val = _dom.match(new RegExp('src="([^"]+)')) [1];
            _dom = document.createElement(name1.replace(/</g, ''));
            _dom.setAttribute(attr, _val);
          }
          result.push(_dom);
          s = e;
        }
        return result;
      };
      $.get(url, data0, function (data) {
        var links,
        styles,
        scripts,
        body;
        if (flag) {
          links = $(data) .find('link');
          styles = $(data) .find('style');
          scripts = $(data) .find('script');
          body = $(data) .find('body') .html();
        } else {
          var start = data.indexOf('<body>'),
          end = data.indexOf('</body>');
          body = data.substring(start + 6, end);
          links = getByTagName(data, '<link', '/>', 'href');
          styles = getByTagName(data, '<style', '</style>');
          scripts = getByTagName(data, '<script', '</script>', 'src');
        }
        target.empty() .append(links) .append(styles) .html(body) .append(scripts);
      }, flag ? 'xml' : undefined);
    };
    var ua = navigator.userAgent;
    return ua && /MSIE/.test(ua) ? Number(ua.match(/MSIEs+([^.]*)/) [1])  : 0;

    这一段代码中就有用到优化了,把navigator.userAgent存到局部变量中,减少了查询次数,如下循环体中经常应用到的代码

    for (var i = 0, len = arr.length;  i < len; i++) {
      // test
    }

    当arr数组的长度固定的时候,我们直接存在变量里,循环体就不会每次都去计算arr数组的长度了,这边贴上一个简单测试的数据(有兴趣的人自己去测试一下,毕竟不同环境,不同代码测出来的效果不一定一样)

    优化过的代码大概运行效率是97%,在大多数脚本中基本都可以忽略不计了,可能这也是IDE代码填补时候直接跳出的都是没有优化过打代码吧。而且在实际应用场景中数据的长度可能经常会变化,在这边我们只是探讨优化的原则。

     原则1:减少查询次数 如: var href = window.location.href;

    if (!data || !name1 || !name2) return 0;

    上面这段代码就运用到了能力检测,这是动态脚本语言中编码的一个习惯,因为不同于Java等强语言具有接口、严格的数据类型,JavaScript只严格区分数据和指令,有一个理论的名字我不太记得了,大致描述的是:

    不会飞,会游泳,2只翅膀的鸟,我就认为是鸭子。

    作者描述的不太准确,不过相信读者能明白这个意思。有另外一句话是:不管白猫、黑猫,能抓到老鼠的就是好猫。 其实也是同一个道理。

    !data,对于数据就是测试这个数据是否存在,对于方法,就是测试这个功能是否存在。

    而这边 return 0;则是用0来代替false,节省了四个字符,不管是在网络传输中(js脚本从后台服务中拉到pc浏览器),还是在脚本解释中都会加快速度。当然在返回值是数字的时候就不应该这么用了。

    原则2:在方法返回布尔型的时候可以用 0 代替 false ,1代替true

    $.get(url, data0, function (data) {
      var links,
      styles,
      scripts,
      body;
      if (flag) {
        links = $(data) .find('link');
        styles = $(data) .find('style');
        scripts = $(data) .find('script');
        body = $(data) .find('body') .html();
      } else {
        var start = data.indexOf('<body>'),
        end = data.indexOf('</body>');
        body = data.substring(start + 6, end);
        links = getByTagName(data, '<link', '/>', 'href');
        styles = getByTagName(data, '<style', '</style>');
        scripts = getByTagName(data, '<script', '</script>', 'src');
      }
      target.empty() .append(links) .append(styles) .html(body) .append(scripts);
    }, flag ? 'xml' : undefined);

    上面这段代码我原本if和else方法做了2种处理,代码逻辑几乎一样,变量名也几乎重复,后面我简单修改了一下,以高内聚低耦合的原则将重复性高的代码提取出来,只处理局部差异,实现了封装。

    getByTagName方法的封装尤其体现了OOP,而不是面向过程开发,如果是每一种情况都去写一个处理过程,也能把代码实现,但难免代码过于冗长。

    原则3:OOP-面向对象编程(即封装)

    flag ? 'xml' : undefined

     这边用 ?: 三元运算符号来代替if else,明显可以把一个语句作为一个变量放在括号里面作为方法的实参,一行代码是三元运算符的一个特色,另外从效率方面,也是三元运算符占优(与if else相比,具体原理作者也不清楚)

    原则4:用三元运算符代替if else

    还有一些代码中没有运用到的技巧,稍微提及一下

    • (‘’ +) > String() > toString() > new String()
    • if else多分支使用的时候要把最有可能的情况靠前写,运用到&&和||等具有短路特性的符号的时候也是这个原则
    • 可以用 var a = b || c;来代替 a = b ? b : c;
    • 可以用 var a = b && b.c && b.c.d;来代替 if (b && b.c) a = b.c.d; 同样 可以用 bool && (a = 1); 来代替 if(bool) a = 1;
    • 把方法存在一个json变量中,你就不用再用if else 一个一个方法名地写出来,直接求出json的key,然后引用json中的方法即可
      var fcJson = {
        1: function() {},
        2: function() {}
      };
      fcJson[key]();
      // 原先的方式
      /*
      switch(key) {
      case 1: fc1(); break;
      case 2: fc2(); break;
      }
      */

  • 相关阅读:
    iOS new Date() 报invalid Date
    Windows查找端口对应进程
    Dbvisualizer Free版本无sql自动提示功能解决方案
    Docker
    更换k8s集群,或者创建集群使用用户不对,导致ranchar无法显示容器处理
    linux下mysql5.7.30安装
    ansible 使用redis缓存
    tr命令
    ipvsadm安装配置NAT
    2019新电脑主板安装win10系统
  • 原文地址:https://www.cnblogs.com/gabin/p/3867291.html
Copyright © 2020-2023  润新知