JavaScript 风格指南(笔记)

变量

  • 使用有意义、可读性好的变量
  • 使用 ES6 的 const 声明常量
  • 对功能相似的变量名采用统一的命名风格
  • 使用易于检索名称git

    举例
    // 反例
    for (var i = 0; i < 525600; i++) {
      runCronJob();
    }
    
    // 正例
    var MINUTES_IN_A_YEAR = 525600;
    for (var i = 0; i < MINUTES_IN_A_YEAR; i++) {
      runCronJob();
    }
  • 使用说明变量(即有意义的变量名)
  • 显式优于隐式(变量名尽可能简洁明了)
  • 避免重复的描述
  • 避免无心义的条件判断github

    举例
    var currentPage='';
    var pageNumInfo = JSON.parse(localStorage.getItem('pageNumInfo'));
    if (pageNumInfo) {
        currentPage = parseInt(pageNumInfo[0].pageNum);
    } else {
        currentPage = 1;
    }
    // 以上代码片断可用如下代码取代
    var pageNumInfo = JSON.parse(localStorage.getItem('pageNumInfo')); 
    var currentPage = parseInt(pageNumInfo[0].pageNum) || 1;

函数

  • 函数参数编程

    函数参数理想状况下应该不超过 2 个。当确实须要多个参数时,大多状况下能够考虑将这些参数封装成一个对象。
  • 保证函数功能的单一性promise

    功能不单一的函数将致使难以重构、测试和理解。功能单一的函数易于重构,并使代码更加干净。
  • 提升函数名的可读性(函数名应明确代表其功能)
  • 函数应该只作一层抽象服务器

    当函数须要的抽象多于一层时一般意味着函数功能过于复杂,需将其进行分解以提升其可重用性和可测试性。
  • 避免在一个函数中写重复的代码
  • 采用默认参数精简代码
  • 使用 Object.assign() 设置默认对象
  • 不要使用标记(Flag)做为函数参数(会破坏函数功能的单一性)
  • 避免反作用数据结构

    函数反作用:当函数产生了除了“接受一个值并返回一个结果”以外的行为时,称该函数产生了反作用。好比写文件、修改全局变量等。
    程序在某些状况下确实须要反作用这一行为,如先前例子中的写文件。这时应该将这些功能集中在一块儿,不要用多个函数/类修改某个文件。用且只用一个 service 完成这一需求。
  • 不要写全局函数
  • 采用函数式编程
  • 封装判断条件
  • 避免“否认条件”的判断
  • 避免条件判断闭包

    许多状况下经过使用多态(polymorphism)能够达到一样的目的。
    // 反例
    class Airplane {
      //...
      getCruisingAltitude() {
        switch (this.type) {
          case '777':
            return getMaxAltitude() - getPassengerCount();
          case 'Air Force One':
            return getMaxAltitude();
          case 'Cessna':
            return getMaxAltitude() - getFuelExpenditure();
        }
      }
    }
    
    // 正例
    class Airplane {
      //...
    }
    
    class Boeing777 extends Airplane {
      //...
      getCruisingAltitude() {
        return getMaxAltitude() - getPassengerCount();
      }
    }
    
    class AirForceOne extends Airplane {
      //...
      getCruisingAltitude() {
        return getMaxAltitude();
      }
    }
    
    class Cessna extends Airplane {
      //...
      getCruisingAltitude() {
        return getMaxAltitude() - getFuelExpenditure();
      }
    }
  • 避免类型判断
  • 避免过分优化
  • 无效代码及时删除

对象和数据结构

  • 使用 getters 和 setters并发

    使用 getters 和 setters 获取对象的数据远比直接使用点操做符具备优点,为何呢??
    一、当须要对获取的对象属性执行额外操做时。
    二、执行 set 时能够增长规则对要变量的合法性进行判断。
    三、封装了内部逻辑。
    四、在存取时能够方便的增长日志和错误处理。
    五、继承该类时能够重载默认行为。
    六、从服务器获取数据时能够进行懒加载。
  • 让对象拥有私有成员。(能够经过闭包实现)

  • 列表项目
  • 单一职责原则(SRP)
  • 开闭原则(OCP)async

    代码实体(类,模块,函数等)应该易于扩展,难于修改。
    即代码模块的功能应该要方便用户拓展而不是修改源码
  • 利斯科夫替代原则(LSP)函数式编程

    子类对象应该可以替换其超类(父类)对象被使用。
  • 接口隔离原则(ISP)

    客户端不该该依赖它不须要的接口,一个类对另外一个类的依赖应该创建在最小的接口上。
  • 依赖反转原则(DIP)

    该原则有两个核心点:
    一、高层模块不该该依赖于低层模块。他们都应该依赖于抽象接口。
    二、抽象接口应该脱离具体实现,具体实现应该依赖于抽象接口。
  • 使用 ES6 的 classes 而不是 ES5 的 Function

    典型的 ES5 的类(function)在继承、构造和方法定义方面可读性较差。
    当须要继承时,优先选用 classes。
    可是,当在须要更大更复杂的对象时,最好优先选择更小的 function 而非 classes。
  • 使用方法链
  • 优先使用组合模式而非继承

测试

  • 单元测试,单一的测试每一个概念

并发

  • 用 Promise 替代回调(支持 ES6 的状况,优先使用)
  • async 和 await(支持 ES7 的状况,优先使用)

错误处理

  • try/catch 捕获异常
  • 不要忽略被拒绝的 promises

格式化

  • 大小写一致
  • 调用函数的函数和被调函数应放在较近的位置

    当函数间存在相互调用的状况时,应将二者置于较近的位置。理想状况下,应将调用其余函数的函数写在被调用函数的上方。

注释

  • 只对存在必定业务逻辑复杂性的代码进行注释。注释并非必须的,好的代码是可以让人一目了然,不用过多无谓的注释。
  • 被注释掉的代码及时删除
  • 不须要版本更新类型注释。须要时可使用 git log 获取历史版本。
  • 避免位置标记
  • 避免在源文件中写入法律评论

参考

相关文章
相关标签/搜索