Code Review最佳实践

65 阅读3分钟

image.png

写代码时易出现的问题

    1. 避免永远 pending 的 Promise

      new Promise(function (resolve, reject) {
        KNB.getLocation({
          success(location) {
            if (location.lat) {
              resolve(location)
            }
      
            // 如果 lat=0,会永远 pending
          }
        })
      })
      
      new Promise(function (resolve, reject) {
        KNB.getLocation({
          success(location) {
            if (location.lat) {
              resolve(location)
            } else {
              reject()
            }
          }
        })
      })
      
    2. 避免价格计算(js 精度问题),直接用 js 进行四则运算会有精度问题,引起用户端展示异常

      1.22 / 100 // = 0.012199999999999999
      0.3 - 0.2 // = 0.09999999999999998
      
      const finalPrice1 = price * 0.8
      const finalPrice2 = priceA - priceB
      const finalPrice3 = result.priceA * 0.97
      

      正确做法:对于 C 端业务,让后端计算好,后端下发字符串,前端只展示、不计算。

    3. JSON.parse要try catch

      在前后端协作中,后端往往会返回一个序列化字符串,需要前端使用 JSON.parse 解析。而后端返回的内容不总是可靠的,建议前端同学 try catch 做好降级方案。
      
      这是个常见问题,到综前端、金融服务前端、服体前端、点评前端均有 COE 案例,含 2S9
    4. Vue 组件错误的默认值

       //错误示例
       export default {
          props: {
            // 这里 prop auditShowConfig 的默认值本意可能是一个空对象,而现在这里的写法实际返回一个 undefined.
            auditShowConfig: {
              type: Object,
              default: () => {}
             }
           }
        }
        
        //正确示例
        export default {
          props: {
            auditShowConfig: {
              type: Object,
              default: () => ({})
            }
          }
        }
    
    1. 避免重新定义同名变量
    //错误示例
    export const fastSignIn = (param) => {
      const param = {
        ...param,
        source: 1
      }
    }
    
    1. 避免使用ts-ignore
    // @ts-ignore
    lx.foo()
    对于没有被 ts 检测到的方法或者属性,应去解决问题而不是使用 `ts-ignore`
  1. 技巧类

    1. //bad
      cosnt obj = {}
      cosnt b = obj.a && obj.a.b
      console.log(b)	// undefined
      //good
      cosnt obj = {}
      cosnt b = obj?.a?.b
      console.log(b)	// undefined
      
    2. //bad
      cosnt a = b === '1'true: false
      
      //good
      cosnt a = b === '1'
      
    3. // bad--->这个方式参数就必须按顺序传递
      const getUserInfo =(name,age,sex,mobile,hobby)=> {
        // 函数逻辑
      }
      // good
      const getUserInfo =(userInfo)=> {
        // 函数逻辑
        const {name,age,sex,mobile,hobby} = userInfo
      }
      
    4. // bad
      const counter =(state=0,action)=>{
        switch (action.type) {
          case 'ADD':
            return state + 1
          case 'MINUS':
            return state - 1
          default:
            return state
        }
      }
      // good
      const counter =(state=0,action)=>{
        const step={
          'ADD':1,
          'MINUS':-1
        }
        return state + (step[action.type] ?? 0)
      }
      
    5. // bad
      const checkGameStatus =()=>{
        if(status===0||(satuas===1&&isEnd===1)||(isEnd===2)){
          // 调用
        }
      }
      // good
      const isGaneOver =()=>{
        return (status===0||(satuas===1&&isEnd===1)||(isEnd===2))
      }
      const checkGameStatus =()=>{
        if(isGameOver()){
          // 调用
        }
      }
      
    6. // bad
      const publishPost =(post)=>{
        if(isLoggenIn){
          if(post){
            if(isPostValid()){
              doPublishPost(post)
            }else{
              throw new Error('文章不合法')
            }
          }else{
            throw new Error('文章不能为空')
          }
        }else{
          throw new Error('用户未登录')
        }
      }
      // good
      const publishPost =(post)=>{
        if(!isLoggenIn){
          throw new Error('用户未登录')
        }
        if(!post){
          throw new Error('文章不能为空')
        }
        if(!isPostValid()){
          throw new Error('文章不合法')
        }
        doPublishPost(post)
      }
      
      // bad
      const createElement =(item)=>{
        if(item.type==='ball'){
          cosnt div = document.createElement('div')
          div.className = 'ball'
          div.style.backgroundColor = item.color
          return div
        }else if(item.type==='block'){
          const div = document.createElement('div')
          div.className = 'block'
          div.style.backgroundColor = item.color
          return div
        }else if(item.type==='square'){
          const div = document.createElement('div')
          div.className = 'square'
          div.style.backgroundColor = item.color
          return div
        }else{
          throw new Error('未知元素类型')
        }
      }
      
      // good
      cosnt createElement =(item)=>{
        const validTypes = ['ball', 'block', 'image']
        if(!validTypes.includes(item.type)){
          throw new Error('未知元素类型')
        }
        cosnt div = document.createElement('div')
        div.className = item.type
        div.style.backgroundColor = item.color
        return div
      }
      // bad
      let commodity = {
        phone: '手机',
        computer: '电脑',
        television: '电视',
        gameBoy: '游戏机',
      }
       
      function price(name) {
        if (name === commodity.phone) {
          console.log(1999)
        } else if (name === commodity.computer) {
          console.log(9999)
        } else if (name === commodity.television) {
          console.log(2999)
        } else if (name === commodity.gameBoy) {
          console.log(3999)
        }
      }
      price('手机') // 1999
      // good
      const commodity = new Map([
        ['phone', 1999],
        ['computer', 9999],
        ['television', 2999],
        ['gameBoy', 3999],
      ])
       
      const price = (name) => {
        return commodity.get(name)
      }
      price('phone') // 1999
      
  2. 可维护性类

    1. // bad
      if (state === 1 || state === 2) {
        // ...
      } else if (state === 3) {
        // ...
      }
      
      // good
      const UNPUBLISHED = 1;
      const PUBLISHED = 2;
      const DELETED = 3;
      
      if (state === UNPUBLISHED || state === PUBLISHED) {
        // ...
      } else if (state === DELETED) {
        // ...
      }
      
    2. // bad
      class User {
        userName;
        userAge;
        userPwd;
      
        userLogin() { };
        userRegister() { };
      }
      
      // good
      class User {
        name;
        age;
        pwd;
      
        login() {};
        register() {};
      }
      
    3. anyScript
    4. 重复代码 — 主要看有没有把公用组件,可复用的代码,函数抽取出来
    5. 代码注释 — 注释不明确或者缺少注释
  3. 边界问题

  4. 性能问题

  5. 安全问题

    1. xss攻击
     React 中使用 `dangerouslySetInnerHTML` 或者 Vue 中使用 `v-html` 都会引入 XSS 攻击风险。
    
     在 JSX 层面处理 HTML 拼接相关逻辑,避免 dangerouslySetInnerHTML 的使用。
     在必需要 dangerouslySetInnerHTML 的地方,增加 excapeHTML() 方法过滤、净化来自用户侧的不可靠内容。