编程技巧

一 接口和面向接口编程

1 用ts编写基于 interface 的命令模式

编写用户界面程序,页面有成百上千个子菜单

约定基于命令模式编写

  • 负责子菜单的同事 完成编程之后会将子菜单封装成一个命令对象,将其交给编写菜单集合界面的同事

约定:调用子菜单的 execute 方法时会执行对应子菜单的命令

class RefreshMenuBarCommand {
  execute() {
    console.log('刷新菜单界面');
  }
}
class AddSubMenuCommand {
  execute() {
    console.log('增加子菜单');
  }
}
class DelSubMenuCommand {
  execute() {
    console.log('删除菜单界面');
  }
}
let refreshMenuBarCommand = new RefreshMenuBarCommand()
let addSubMenuCommand = new AddSubMenuCommand()
let delSubMenuCommand = new DelSubMenuCommand()

let setCommand = command => {
  document.getElementById('execCommand').onclick = () => commond.execute()
}
setCommand(refreshMenuBarCommand)
setCommand(addSubMenuCommand)
setCommand(delSubMenuCommand)
防止某个子命令对象没有实现 execute 方法,在高层函数中添加一段防御性代码
let setCommand = command => {
  document.getElementById('execCommand').onclick = () => {
    if(typeof command.execute !== 'function') {
      throw new Error('command对象必须实现execute方法')
    }
    commond.execute()
  }
}

2 ts版本的命令模式

1. 定义 Command 接口
interface Command {
    execute: Function;
}
2. 定义类
class RefreshMenuBarCommand implements Command {
    constructor() {}
    execute() {
        console.log('刷新菜单界面');
    }
}
class AddSubMenuCommand implements Command {
    constructor() {}
    execute() {
        console.log('增加子菜单');
    }
}
class DelSubMenuCommand implements Command {
    constructor() {}
    execute() {
        console.log('删除菜单界面');
    }
}

二 代码重构

1 提炼函数

  • 避免出现超大函数
  • 独立出来的函数
    • 有助于代码复用
    • 更容易被覆写
    • 如果拥有一个良好的命名,它本身就起到了注释的作用

2 合并重复的条件片段

function paging(currPage) {
 if(currPage <= 0) {
    currPage = 0;
    jump(currPage);
  } else if(currPage >= totalPage) {
    currPage = totalPage;
    jump(currPage);
  } else {
    jump(currPage);
  }
}

独立重复代码

function paging(currPage) {
  if(currPage <= 0) {
    currPage = 0;
  } else if(currPage >= totalPage) {
    currPage = totalPage;
  } 
  jump(currPage);
}

3 把条件分支语句提炼成函数

规则:夏季全部商品打八折出售

function getPrice(price) {
  let date = new Date();
  if(date.getMonth() >= 6 && date.getMonth() <= 9) {
    return price * 0.8;
  }
  return price;
}

提炼条件分支语句

更准确地表达代码的意思,函数名本身又能起到注释的作用

function isSsummer() {
  let date = new Date();
  return date.getMonth() >= 6 && date.getMonth() <= 9;
}
function getPrice(price) {
  if(isSummer()) {
    return price * 0.8;
  }
  return price;
}

4 合理使用循环

5 提前让函数退出代替嵌套条件分支

函数只有一个出口

function del(obj) {
  let ret;
  if(!obj.isReadOnly) {
    if(obj.isFolder) {
      ret = deleteFolder(obj);
    } else if(obj.isFile) {
      ret = deleteFile(obj);
    }
  }
  return ret;
}

翻转外层if判断

function del(obj) {
  let ret;
  if(obj.isReadOnly) {
    return;
  }
  if(obj.isFolder) {
    ret = deleteFolder(obj); 
  } else if(obj.isFile) {
    ret = deleteFile(obj);
  }
  return ret;
}

6 传递对象参数代替过长的参数列表

7 尽量减少参数数量

8 少用三目运算符

9 合理使用链式调用

让方法调用结束后返回对象自身

class User {
  constructor() {
    this.id = null;
    this.name = null;
  }
  setId(id) {
    this.id = id;
    return this;
  }
  setName(name) {
    this.name = name;
    return this;
  }
}
console.log(
  new User().setId(12).setName('lisi')
);
  • 若其中一步出错,增加调试难度
  • 若链条容易发生改变,导致调试和维护困难

10 分解大型类

街头霸王

class Spirit {
  constructor(name) {
    this.name = name;
  }
  attack(type) {
    if(type === 'waveBoxing') {
      console.log(this.name + ': 使用波动拳');
    } else if(type === 'whirlKick') {
      console.log(this.name + ': 使用旋风腿');
    }
  }
}
  • attack 方法过于庞大 -> 有必要作为一个单独的类
class Attack {
  constructor(spirit) {
    this.spirit = spirit;
    this.list = {};
    this.init()
  }
  start(type) {
    return this.list[type].call(this)
  }
  init() {
    this.list = {
      waveBoxing() {
        console.log(this.spirit.name + ': 使用波动拳');
      },
      whirlKick() {
        console.log(this.spirit.name + ': 使用旋风腿');
      }
    }
  }
}
class Spirit {
  constructor(name) {
    this.name = name;
    this.attackObj = new Attack(this);
  }
  attack(type) {
    this.attackObj.start(type);
  }
}

11 return 退出多重循环

  • break -> return
  • 把循环后面的代码放到return后面
    • 代码多 -> 提炼成函数
posted on 2023-05-09 10:54  pleaseAnswer  阅读(9)  评论(0编辑  收藏  举报