JavaScript之代码重构

记录平时JS代码重构的经验,React代码重构也是基于JS重构

1、提炼函数

坏味道:函数过长,不得不加上很多注释。
我们要做的就是独立函数,函数体内逻辑应该清晰明了。好处是:

  • 避免出现超大函数,提高观赏性
  • 独立函数有助于代码复用
  • 更容易被覆写

示例:略

2、拆分判断条件

坏味道:复杂的条件分支语句,导致程序难以阅读和理解。

let getPrice = function(price){
  let date = new Date();
  //观察这段代码
  if(date.getMouth() >= 6 && date.getMouth() <= 9){
      return price * 0.8;
  }
  return price;
}

解析:代码表达的意思 和代码自身还存在一些距离,阅读人员必须要花一些精力才能证明它传达的意图。如果条件再长些,更难理解。

 if(date.getMouth() >= 6 && date.getMouth() <= 9){
      return price * 0.8;
  }

理想状态:单独提炼函数,函数命名语义化!既能准确表达代码的意思,本身又能起到注释的作用。

let isSummer = function(){
  let date = new Date()
  return date.getMouth() >= 6 && date.getMouth() <= 9
}

let getPrice = function(price){
  if(isSummer()){
    return price * 0.8;
  }
  return price;
}

3、提前退出 代替 嵌套If

坏味道:嵌套的条件分支绝对是代码维护者的噩梦

let del = function(obj){
  let ret;
  if(!obj.isReadOnly){
    if(obj.isFolder){ //如果是文件夹
      ret = deleteFolder(obj;)
    }else if(obj.isFile){ //如果是文件
      ret = deleteFile(obj); 
    }
  }
  return ret;
}

解析: 实际上,如果对函数的其他部分不感兴趣,那就应该立即退出。引导读者去看一些没有用的else片段,只会妨碍他们对程序的理解。
改造之后~

let del = function(obj){
  if(obj.isReadOnly) return; //反转if表达式

  if(obj.isFolder){
    return deleteFolder(obj);
  }

  if(obj.isFile){
    return deleteFile(obj);
  }
}

这样是不是好多了😋

4、传递参数不要长,标记不要做参数

坏味道:函数可能接受多个参数,参数数量越多,函数越难以理解。使用者需要搞明白全部参数的含义。
优化措施

  • 可以用对象代替多参数
//bad
function show(id,name,address,sex,mobile){
  //TODO
}

//good
function show(person){
  //TODO  person = {id,name,address,sex,mobile} 
}
  • 优化函数逻辑 ,控制在 3个参数以内最佳。

function show(arg1,arg2,arg3){}
这条不记得是哪位大神说的,不过根据个人经验来说,蛮有用的~

  • boolean类型的标记 不要做参数。

标记告诉你的用户这个函数做的事情不止一件。但是函数应该只做一件事。如果你的函数中会根据某个布尔参数产生不同的分支,那就拆分这个函数。

//标记告诉你的用户这个函数做的事情不止一件。但是函数应该只做一件事。如果你的函数中会根据某个布尔参数产生不同的分支,那就拆分这个函数。

// Bad
function createFile(fs,name, temp) {
  if(temp) {
    fs.create("./temp/"+ name);
  } else{
    fs.create(name);
  }
}
// Good 这里函数写的比较短,实际函数是很长的,性价比高。
function createTempFile(fs,name) {
  fs.create("./temp/"+ name);
}
function createFile(name) {
  fs.create(name);
}

const  getFile = temp ? createTempFile(fs,name) : fs.create(name);

5、合理使用三目

坏味道:有些程序员喜欢大规模使用三目运算符。直白的说,过分嵌套三目,其损失的可读性和可维护性,相对于节约的代码量来说,因小失大。
例如:

// 逻辑简单可用三目
let global = typeof window != 'undefined' ? window : this;

// 复杂逻辑,使用三目 bad!!!
if(!aup || !bup){
  return a === doc ? -1 :
    b === doc ? 1 : aup ? -1; bup ? 1 : sortInput ? true : 0;
}

6、巧用return 推出函数

其实之前已经用到过return了,这里再单独说下
坏味道:假如函数体中有一个两重循环语句,我们需要在内层循环中判断,当达到某个临界条件时,退出外层的循环。 于是出现了 引入控制变量这个操作:

let func = function(){
  outerloop;
  for(var i = 0; i< 10; i++){
    innerloop;
    for(var j = 0;j< 10;j++){
      if(i * j > 30){
        break outerloop
      }
    }
  }
}

更简单的做法是,在需要终止循环的时候直接退出整个方法

let func = function(){
  for(var i = 0; i< 10; i++){
    for(var j = 0;j< 10;j++){
      if(i * j > 30){
        return print('执行完成,退出' + i * j);
      }
    }
  }
}

7、善用符号常量

坏味道:代码中莫名其妙的数字,着实让人摸不着头脑。

if(temperature > 32){ //此处的32 并不知道要表达什么?
  //TODO...    
}

解析:利用符号常量 + 注释的方式,使代码一目了然。TS中符号常量可进而抽取为 枚举TypeScript

/** 临界温度 */
const FREEZING = 32;
...
if(temperature > FREEZING_POINT){
  //TODO...
}

8、避免副作用

坏味道:理想情况下 ,一个函数,处理的数据来自于形参。如果一个函数中即引用了形参,又引入了全局变量。其已经具有了破坏性,会导致古怪的时序性耦合及顺序依赖。
例如:

let name = "Ryan McDermott";

function splitIntoFirstAndLastName() {
  name = name.split(" "); 
}
splitIntoFirstAndLastName();

console.log(name); // ["Ryan", "McDermott"];
// 如果另一个函数中使用了name,就有可能因为name是数组而不能正常运行。

我们来优化下

function splitIntoFirstAndLastName(name) {
  return name.split(" "); //通过形参传入,避免了难以捕获的 依赖问题。
}
var name = "Ryan McDermott"
var newName = splitIntoFirstAndLastName(name);
console.log(name); // "Ryan McDermott";
console.log(newName); // ["Ryan", "McDermott"];


9、优化if

坏味道:if判断过多, 虽然能运行,但是很丑陋,怎么改善。

function excute(key){
  if(key === "A" ){
     return //something ...
  }
  if(key === "B"){
     return //something1 ...
  }
  if(key === "C"){
     return//something2 ...
  }
   if(key === "D){
     return//something3 ...
  }
}

优化之后


let func = {
  "A":()=>{
    //something ...
  },
  "B":()=>{
    //something1 ...
  },
  "C":()=>{
    //something2 ...
  },
  "D":()=>{
    //something3 ...
  }
}

let excute = key => func[key] && func[key]();

补充:

代码命名规范
CODELF

实际开发中,很多都不是自己写的代码。面对之前的屎山,我想应该在不影响既有功能的前提下,refactoring it!同时确保自己尽量不要写shi代码。即是技术,也是艺术。

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值