• (第一章)改善JavaScript,编写高质量代码。


    根据《编写高质量代码改善JavaScript程序的188个建议》这本书,来记录我目前所了解的建议方式。

    建议1:警惕Unicode乱码

    根据ECMA标准规定JavaScript语言可以使用中文来命名变量或函数名,例如:
    
    var 人名 = “张三”;
    function 睡觉(谁){
      alert(谁 + ":快睡觉!都半夜三更了。");
    }
    
    睡觉(人名);
    
    但是在ECMA标准化之前,JavaScript通常是不支持Unicode编码的,为了防止乱码,我们应该尽量使用基本字符进行编码。
    建议1

    建议2:正确辨析JavaScript句法中的词、句和段

    {
     //对象
    }
    
    function(){
     //函数
    }
    
    if(){
     //条件
    }
    
    for(){
     //循环
    }
    
    while(){
     //循环
    }
    
    switch(){
     //多条件
    }
    
    with(){
     //作用于
    }
    
    try(){
      //异常处理
    }
    建议2

    建议3:减少全局变量污染

    在任何函数外面直接执行var语句
    var f = “value”;
    
    直接添加一个属性到全局对象上,全局对象是所有全局变量的容器,在Web浏览器中,全局对象名为window
    window.f = “value”;
    
    直接使用未经声明的变量,以这种方式定义的全局变量被称为隐式的全局变量
    f = “value”;
    建议3

    建议4:注意JavaScript数据类型的特殊性

    1.防止浮点数溢出
    
    num = 0.1+0.2; //0.3000000000000000004
    
    针对上面相加可以这么进行处理:
    
    a = (1+2)/10; //0.3
    
    2.慎用JavaScript类型自动转换
    
    
    
    
    
     
    
     3.正确检测数据类型
    
    
    
    4.避免误用parseInt
    
    parseInt("123abc");  //123     parseInt("1.73"); //1        parseInt(".123"); //NAA
    
    var d = "010";  //八进制   var e ="0x10";   //十六进制     parseInt(d); //8  parseInt(e); //16
    建议4

    建议5:防止JavaScript自动插入分号

    JavaScript会在解析时,自动在后面插入一个分号,但是在某些情况下是不允许插入分号的,否则会导致代码出错,例如:
    
    var f = function(){return{status : true};
    
    JavaScript 应该正确安全的实行 分行 显示,例如
    
    var i = a ? 1 : b ? 2 : c ? 3 : 4;  //定义一个变量i,然后为其赋值,如果变量a为true则赋值为1,否则就判断变量b,如果b为true则赋值为2,否则就判断变量c,如果c为true则赋值为3,否则就赋值为4
    
    应该写成
    
    var i = a ? 1
              :b ? 2
              :c ? 3
              :4 ;
    建议5

    建议6:正确处理JavaScript特殊值

    建议7:小心保留字的误用

    Javascr不建议使用任何保留字。如果一定要使用保留字,必须要用引号括起来,例如
    
    object = {'case' : value};
    
    object['case'] = value;
    建议7

    建议8:谨慎使用运算符

     1. 用 ===,而不用 ==
    
    ' ' == 0 //false
    0 == ' ' //true
    0 == '0' //true
    false == 'false' //false
    false == '0' //true
    falser == undefined //false
    false == null //false
    null == undefined //true
    
    2.谨慎使用 ++ 和 --
    
    var n = 4;
    n++;   
    ++n;
    
    3.小心逗号运算符
    
    var a = (1,2,3,4);
    alert(a); //4
    
    a=1,2,3,4;
    alert(a);  //1
    建议8

    建议9:不要信任 hasOwnProperty

    20

    建议10:谨记对象非空特性

    21

    建议11:慎重使用伪数组

    21

    建议12:避免使用with

    22

    建议13:养成优化表达式的思维方式

    对于一个表达式稍加改动就会打乱表达式的逻辑运算顺序,因此我们应该学会优化表达式的结构。
    
    1.第一种方式--加小括号
    
    (a + b > c && a - b < c || a > b > c);
    
    优化:
    
    ((a + b > c) && ((a - b < c) || (a > b > c)));
    
    2.第二种方式--改变表达式结构顺序
    
    例如,想要设计一个表达式来筛选学龄人群,既年龄大于或等于6岁且小于18岁的人,或者年龄大于或等于65岁的人
    
    if(age >= 6 && age < 18 || age >= 65){}
    
    优化:
    
    if(6 <= age && age < 18 || 65 <= age){}
    建议13

    建议14:不要滥用eval

    eval是一个被滥用的很严重的JavaScript特征,通常情况下,eval函数传递一个字符串给JavaScript编译器,该字符串会被当成一段JavaScript程序来解析和执行,例如
    
    eval(alert('提示'));
    
    使用eval形式的代码会更难阅读,而且会使代码性能显著降低。
    建议14

    建议15:避免使用continue

    continue语句与break语句用法相似,在循环结构中用于控制逻辑的执行方向。break语句用于停止循环,而continue语句则用于再次执行循环,与break语句语法相同。
    
    书上讲到,通过重构移动continue语句会使性能得到改善,在非必要条件下,建议不要使用continue语句。
    
    但是,那break呢,是不是也可以不使用,从而使代码性能得到改善。
    建议15

    建议16:防止switch贯穿

    说白了,在写switch  case  break  default的时候,在写case之后,因为并没有指明终点,所以一定要写break,不然会使代码发生连续贯穿现象。
    建议16

    建议17:块标签并非多余

    在写if逻辑判断的时候,即使得到的条件只有一条,也应写上块标签,例如
    
    if(0){
      if(1){
        alert(1);
      }
    }
    else{
      alert(0);
    }
    
    严格遵循规范,并始终使用代码块,会使代码更容易理解。
    建议17

    建议18:比较function语句和function表达式

    建议19:不要使用类型构造器

     空

    建议20:不要使用new

    建议21:推荐提高循环性能的策略

    建议22:少用函数迭代

    本地数组对象新增加了一个forEach方法,此方法遍历一个数组的所有成员。
    
    JavaScript:
    
    items.forEach(function(value,index,array){
      process(value);
    });
    JQuery:
    
    $.each(items,function(index,value){
      process(value);
    });
    
    尽管基于函数的迭代使用起来非常便利,但是比基于循环的迭代更慢一些,每个数组项要关联额外的函数调用是造成速度慢的主要原因。因此,在非特殊需求下,不建议使用函数迭代。
    建议22

    建议23:推荐提高条件性能的策略

    //条件少
    
    if(found){
    }else{
    }
    
    //条件多
    
    switch(color){
      case "red":
               break;
      case "blue":
               break;
    
      case "brown":
               break;
    
      default:
    }
    
    在大多数情况下,switch比if运行更快,但是只有当条件体数量很大时才明显,它们之间主要性能区别在于,当条件体增加时,if性能负担增加的程度比switch更大,因此,在性能上讲,如果条件体少,应使用if,如果条件体多,应使用switch。
    建议23

    建议24:优化if逻辑

    if(value < 5){
    }else if(value >5 && value <10){
    }else{
    }
    
    可以看得出,如果条件体value大多在小于5的情况下,是最优的,但是在大于5且小于10之间,需要通过一次条件判断,如果大于10,就需要判断3次,所以,得根据情况写if逻辑
    建议24

    建议25:恰当选用if和switch

    表达式的值是连续的线性判断,显然用if结构会更合适一些,例如:如果分数小于60,不及格,分数在60~75(不包括75),合格,分数在75~85(不包括85),良好,分数在85~100,优秀
    
    if(score < 60){
      alert("不及格");
    }else if (60 <= score < 75){
      alert("及格");
    }else if (75 <= score < 85){
      alert("良好");
    }else if(85 <= socre <= 100){
      alert("优秀");
    }
    
    对于有限制的枚举数据,比如性别,使用switch结构会更高效,例如:
    
    switch(sex){
      case "女“:
        alert("女士");
      break;
      case "男“:
        alert("男士");
      break;
      default:
        alert("请选择性别");
    }
    建议25

    建议26:小心if嵌套的思维陷阱

    人的思维是很复杂的,一般遇到一些逻辑判断的时候,人们会
    
    if(a){
      if(b){
          if(c){
            if(d){
              alert("所有条件都成立!");
            }
            else{
              alert("条件d不成立!");
            }
         }
         else{
           alert("条件c不成立!");
         }
       }
       else{
         alert("条件b不成立!");
       }
    }
    else{
      alert("条件a不成立");
    }
    
    一般可以采用排除法来优化上面例子
    
    var t = true; //初始化为true
    if(!a){
      alert("条件a不成立!");
    
      t=false;
    }
    
    if(!b){
      alert("条件b不成立!");
    
      t=false;
    }
    
    if(!c){
      alert("条件c不成立!");
    
      t=false;
    }
    
    if(!d){
      alert("条件d不成立!");
    
      t=false;
    }
    
    if(t){
      alert("所有条件都成立!");
    
    }
    
    排除法虽然有效地避免了条件结构的多重嵌套,并且更加符合人的思维模式,但是,也是有一定的局限性,在条件判断时,如果有一个发生错误,那就会终止,放弃后面的操作,如果仅仅是为了检查某个值的合理性,也就无所谓了,但是如果为了改变变量值和数据操作,那么直接放弃就会让后面的数据操作也无法进行,为了防止此类问题,可以再设计一个标志变量来跟踪整个操作行为。
    建议26

    建议27:小心if隐藏的Bug

    很多程序员会犯过这样的低级错误:
    if(a = 1){
      alert(a);
    }
    虽然它是一个合法的表达式,不会导致编译错误,但是由于此表达的返回值为非0数值,JavaScript会自动把它转化为true,因此这样的分支结构的条件永远成立。
    为了防止出现这样低级而令人讨厌的错误,我们建议:
    if(1 == a){
      alert(a);
    }
    建议27

    建议28:使用查表法提高条件检测的性能

    当有大量离散值需要测试时,使用if和switch比使用查表法要慢得多,在JavaScript中查表法可通过数组或普通对象实现。
    查表法访问数据,在条件体的数目很大时,查表法不仅非常快,而且当需要测试的离散值数量非常大时,也有办法保持代码的可读性。
    例如,使用switch检测value值。
    switch(value){
      case 0:
        return result0;
      case 1:
        return result1;
      case 2:
        return result2;
      case 3:
        return result3;
      case 4:
        return result4;
    }
    使用switch结构检测value值的代码所占的空间可能与switch的重要性不成比例,代码很笨重,整个结构可以用一个数组查询代替。
    var result = [result0,result1,result2,result3,result4]
    return results[value];
    建议28

    建议29:准确使用循环体

    选择正确的循环体会有助于提高性能及用户体验,一般来讲,有四种循环方式。例如:
    1.for(var i=0;i<10;i++){//循环体}
    2.var i=0; while(i<10){//循环体 i++;} //条件循环
    3.var i=0;do{//循环体}while(i++ < 10); //至少循环一次
    4.for(var prop in object){//循环体}
    
    其他循环体会比for in 循环快7倍,因此推荐这样做,除非需要对数目不详的对象属性进行操作,否则避免使用for in循环,例如,迭代遍历一个有限的、已知的属性列表,舒勇其他循环类型更快,具体的使用模式如下:
    var prop = ["prop1","prop2"],i=0;
    while(i<prop.length){ process(object[prop[i]]);}
    
    if循环是有章可循的,我们可以很容易地预知循环的次数,每次循环的状态等信息。
    while循环根据特定条件来决定循环操作,由于这个条件是动态的,无法预知条件何时为ture和flase。
    
    因此,for结构尝尝呗用于有规律的重复操作,如数组、对象、集合。
    对于对象的迭代操作,更适合用for in这种特殊的for循环来操作。
    如果对条件有特殊要求的话,建议用while。
    如果至少要执行一次的话,建议用do while。
    建议29

    建议30:使用递归模式

    那么什么叫递归呢?所谓递归函数就是在函数体内调用本函数。
    最简单的例子就是计算阶乘。0和1的阶乘都会被定义为1,更大的数的阶乘是通过计算1*1*...来求得的,每次增加1,直至达到要计算阶乘的那个数。
    function factorial(n){
      if(n<=1){
        return 1;  
      } 
      else{
        return n*factorial(n-1);
      }
    }
    建议30

    建议31:使用迭代

    合并排序算法是最常用的以递归实现的算法。
    function merge(left,right){
      var result=[];
      while(left.length>0&&right.length>0){
        if(left[0]<right[0]){
          result.push(left.shift()); 
        }else{
          result.push(right.shift());
        }
      }
       return result.concat(left).concat(right);
    }
    
    
    function mergeSort(items){
      if(items.length == 1){
        return items;
      }
      var middle = Math.floor(items.length/2), 
            left      = items.slice(0,middle),
            right    = items.slice(middle);
      return merge(mergeSort(left),mergeSort(right));
    }
    
    这个合并排序代码相当简单直接,其中mergeSort()函数被调用得非常频繁,对一个超过1500项的数组进行操作,就可能在Firefox上导致栈溢出,这就说明递归不是最好的实现方法,合并排序算法还可以用迭代实现,例如:
    function mergeSort(items){
      if(items.length == 1){
        return items;
      }
      var work = [];
      for(var i = 0 , len = items.length; i<len; i++){
        work.push([items[i]]);
      }
      work.push([]);
      for(var lim = len; lim > 1; lim=(lim+1) / 2){
        for(var j = 0,k = 0; k<lim; j++,k+=2){
          work[j] = merge(work[k],work[k+1]);
        }
        work[j] = [];
      }
      return work[0];
    }
    建议31

    建议32:使用制表

    建议33:优化循环结构

    循环是最浪费资源的一种流程。循环结构中一点小小的损耗都会被成倍放大,从而影响程序运行的效率。
    1.优化结构
    var a = true;
    for(var b = 1; b < 10; b++){ //循环结构
      if(a == true){
        //条件判断
      }
    }
    很明显,在这个循环结构中if语句会被反复执行,如果这个if语句是一个固定的条件检测表达式,也就是说,如果if语句的条件不会受循环结构的影响,那么不妨采用如下的结构来设计:
    if(a == true){ //条件判断
      for(var b=1;b<10;b++){
        //循环结构
      }
    }
    但是,如果这个if条件表达式受循环结构的制约,就不能够采用这种结构嵌套了。
    建议33
  • 相关阅读:
    让c像python一样可以在命令行写代码并且编译
    动态链接库找不到 : error while loading shared libraries: libgsl.so.0: cannot open shared object file: No such file or directory
    为什么shell中变量赋值不能有空格
    在hyper安装openwrt
    linux扩展lvm磁盘
    docker的基本使用
    tmux与vim主题不一致
    linux centos cli all proxy
    couchDB入门
    tmux复制到windows剪贴板/粘贴板的坑
  • 原文地址:https://www.cnblogs.com/xueweijie/p/7837324.html
Copyright © 2020-2023  润新知