重构你的javascript代码

重构,对于每一个开发者都相当重要,特别是对于那些须要进阶的高级程序员。根据二八理论,20%的重构方法,能解决80%的坏代码。笔者最近查阅较多js编码指南以及从新阅读了《代码整洁之道》、《重构:改善既有代码的设计》两本经典书籍(强烈建议每隔一段时间看,每次都有新体会),整理出如下几个要点,帮助你们以最小的记忆,重构大部分坏代码。若是想全面了解重构方式,能够看笔者整理的AI Javascript风格指南javascript

坏代码判断

坏代码对每一个人、每一个项目标准都不同,但如下几点大几率会是坏代码,须要使用重构方法进行代码重构。css

  • 重复代码
  • 过长函数
  • 过大的类
  • 过长参数列表

重构方法

1. 好的命名

好的命名贯穿整个软件编码过程,好命名包括合理使用大小写定义、缩进等。目前前端工程提供不少lint或format工具,能很方便的帮助工程检测和自动化,不清楚的同窗能够看看笔者AI前端工具链。无论是变量名、函数名或是类名,一个好的命名会加快自身开发效率以及阅读代码效率,毕竟程序读的次数会比写的次数多的多。读github上优秀源码就知道,有时候只要看函数名就知道做者的意图。html

// bad
var yyyymmdstr = moment().format('YYYY/MM/DD');

// good
var yearMonthDay = moment().format('YYYY/MM/DD');
复制代码
// bad
function dateAdd(date, month) {
  // ...
}

let date = new Date();
dateAdd(date, 1) // 很难理解dateAdd(date, 1)是什么意思。笔者注:这里单拎出来举例很简单易懂,但但愿在作工程时也时刻谨记这条

// good
function dateAddMonth(date, month) {
  // ...
}

let date = new Date();
dateAddMonth(date, 1);
复制代码

2. 函数单一职责

软件工程中最重要原则之一。刚毕业不久的开发人员容易出现这个问题,以为业务逻辑很复杂,没办法再细分红单独函数,写出很长的业务函数。但根据笔者指导小伙伴经验,大多数是临时变量过多,致使看不穿业务逻辑的本质;其实重构过程当中一步步分解职责,拆分红细小函数并用恰当的名称命名函数名,能很快理解业务的本质,说不定还能发现潜藏的bug。前端

// bad
function handle(arr) {
    //数组去重
    let _arr=[],_arrIds=[];
    for(let i=0;i<arr.length;i++){
        if(_arrIds.indexOf(arr[i].id)===-1){
            _arrIds.push(arr[i].id);
            _arr.push(arr[i]);
        }
    }
    //遍历替换
    _arr.map(item=>{
        for(let key in item){
            if(item[key]===''){
                item[key]='--';
            }
        }
    });
    return _arr;
}

// good
function handle(arr) {
    let filterArr = filterRepeatById(arr)
    return replaceEachItem(filterArr)
}
复制代码

3. 经过引入解释性变量或函数,使得表达更清晰

// bad
if (platform.toUpperCase().indexOf('MAC') > -1 && browser.toUpperCase().indexOf('IE') > -1 && wasInitialized() && resize > 0) {
  // do something
}

// good
let isMacOs = platform.toUpperCase().indexOf('MAC') > -1
let isIEBrowser = browser.toUpperCase().indexOf('IE') > -1
let isResize = resize > 0
if (isMacOs && isIEBrowser && wasInitialized() && isResize) {
  // do something
}
复制代码
// bad
const cityStateRegex = /^(.+)[,\\s]+(.+?)\s*(\d{5})?$/;
saveCityState(ADDRESS.match(cityStateRegex)[1], ADDRESS.match(cityStateRegex)[2]);

// good
var cityStateRegex = /^(.+)[,\\s]+(.+?)\s*(\d{5})?$/;
var match = ADDRESS.match(cityStateRegex)
let [, city, state] = match
saveCityState(city, state);
复制代码
// bad
if (date.before(SUMMER_START) || date.after(SUMMER_END)) {
  charge = quantity * _winterRate + _winterServiceCharge
} else {
  charge = quantity * _summerRate
}

// good
if (notSummer(date)) {
  charge = winterCharge(quantity)
} else {
  charge = summerCharge(quantity)
}
复制代码

4. 更少的嵌套,尽早 return

// bad
let getPayAmount = () => {
  let result
  if (_isDead) result = deadAmount()
  else {
    if (_isSeparated) result = separatedAmount()
    else {
      if (_isRetired) result = retiredAmount()
      else result = normalPayAmount()
    }
  }

  return result
}

// good
let payAmount = () => {
  if (_isDead) return deadAmount()
  if (_isSeparated) return separatedAmount()
  if (_isRetired) return retiredAmount()
  return normalPayAmount()
}
复制代码

5. 以HashMap取代条件表达式

// bad
let getSpeed = type => {
  switch (type) {
    case SPEED_TYPE.AIR:
    return getAirSpeed()
    case SPEED_TYPE.WATER:
    return getWaterSpeed()
    ...
  }
}

// good
let speedMap = {
  [SPEED_TYPE.AIR]: getAirSpeed,
  [SPEED_TYPE.WATER]: getWaterSpeed
}
let getSpeed = type => speedMap[type] && speedMap[type]()
复制代码

其余

实践以上列举的重构方法,能解决项目中大部分的坏代码,但还有许多重构方法,能让你的代码变得干净整洁易于阅读。java

  • 清晰的项目目录结构
  • ES6+语法糖
    • arrow function
    • rest
    • 函数默认参数
    • async/await
    • let/const 代替var
    • Array Methods
  • 经常使用所有使用const,并字母所有为大写
  • 使用合适的函数名或变量名代替注释
  • 善于利用js中的&& 与 ||
  • 避免‘否认状况’的判断
  • 尽可能不写全局函数与变量
  • 采用函数式编程,ES6 Array支持的很好
  • 移除重复的代码
  • 移除注释的代码

参考文章

相关文章
相关标签/搜索