十个提高前端JS代码质量的小技巧

1、使用更严谨的判断语句

Before:

function getData(val) {
  // val is 'A' or 'B'
  if (val === 'A') {
    // A code
  } else {
    // B code
  }
}

After:

即使val只有两种可能性,也使用精确的判断语句,未来值扩展时能保证相应的方法不受影响,也有助于提高可读性

function getData(val) {
  // val is 'A' or 'B'
  if (val === 'A') {
    // A code
  } else if (val === 'B') {
    // B code
  }
}

2、让内容更易被追溯

Before:

check在命名时没有精确指向具体内容,编辑器检索check变量时,将会返回check、checkName、checkAge的相关结果,追溯成本变高

const data = {
  check: false,
  checkName: false,
  checkAge: false
}

After:

使用更精确的命名法则,提升代码的可读性与可追溯性

const data = {
  checkType: false,
  checkName: false,
  checkAge: false
}

3、直截了当地返回结果

示例1

Before:

function getData(val) {
  if (val === 'A') {
    return true
  } else {
    return false
  }
  // or 
  return val === 'A' ? true : false
}

After:

针对布尔值结果可直接返回运算式本身

function getData(val) {
  return val === 'A'
}

示例2

Before:

function getData(val) {
  if (val === 'A') {
    return 'A'
  } else if (val === 'B') {
    return 'B'
  } else if (val === 'C') {
    return 'C'
  }
}

After:

针对使用结果与判定依据都是变量自身时,使用集合式判断直接输出自身

function getData(val) {
  if (['A', 'B', 'C'].includes(val)) {
    return val
  }
}

4、用对象处理值的映射关系

示例1

Before:

function getDict(val) {
  switch(val) {
    case '0':
      return '选项1'
      break
    case '1':
      return '选项2'
      break
    case '2':
      return '选项3'
      break
    default: 
      return '没有值'
  }
}

After:

从0开始的有序枚举使用数组来定义,更简洁明了的书写方式,且无视val值是字符串或数字类型,适用于有序且少量枚举时

function getDict(val) {
  return ['选项1', '选项2', '选项3'][val] || '没有值'
}

示例2

Before:

function getDict(val) {
  switch(val) {
    case 'A':
      return '选项1'
      break
    case 'B':
      return '选项2'
      break
    case 'C':
      return '选项3'
      break
    default: 
      return '没有值'
  }
}

After:

非数值型或数值型的值都可以使用对象来定义,数值型仍无视val值是字符串或数字类型

function getDict(val) {
  return {
    A: '选项1',
    B: '选项2',
    C: '选项3'
  }[val] || '没有值'
}

function getDict(val) {
  return {
    '-1': '选项1',
    '2': '选项2',
    '3': '选项3'
  }[val] || '没有值'
}

5、减少不必要的引用关系

示例1

Before:

const columns = [{
  label: '姓名',
  prop: 'name'
}, {
  label: '年龄',
  prop: 'age'
}]

const data = {
  columns: columns
}

After:

const data = {
  columns: [{
    label: '姓名',
    prop: 'name'
  }, {
    label: '年龄',
    prop: 'age'
  }]
}

6、用对象囊括相应的变量

Before:

const data = {
  dialogTitle: '添加用户',
  dialogWidth: '50%',
  dialogType: 'add',
  dialogVisible: false,
  dialogComponent: demoItem
}

After:

const data = {
  dialog: {
    title: '添加用户',
    width: '50%',
    type: 'add',
    visible: false,
    component: demoItem
  }
}

7、用适合的方式匹配数组中的项

操作对象数组项时

单项操作

Before:

性能优,但可读性与可维护性差,数据源缺乏可追溯性,不知道具体操作的是哪个项,后期对数组增删数据时,相应的索引可能会产生变化

list[1].hidden = false

After:

性能良,可读性与可维护性强,直观看到操作的是哪个数据项,可以通过关键属性快速检索到相应代码,后期对数组增删数据时该方法都不受影响

list.find(item => item.prop === 'name').hidden = false

多项操作

Before:

性能差(非绝对),多次书写,多次遍历

list.find(item => item.prop === 'name').hidden = false
list.find(item => item.prop === 'age').hidden = false
list.find(item => item.prop === 'sex').hidden = false

After:

性能良(非绝对),仅遍历一次,并且保持find方法的可读性与可维护性

for (const item of list) {
  if (['name', 'age', 'sex'].includes(item.prop)) {
    item.hidden = false
  }
}

注:如若list数组长度过大,且匹配的项都在数组末尾时,After中的示例性能可能变得更差,After中的示例适用于大部分场景,但并非绝对,需依具体场景做决策


8、同类事务都交由单个方法处理

Before:

const inputEvent = {
  change: val => {
    if (val) {
      setData(val)
    } else {
      data.content = ''
    }
  }
}

async function setData(val) {
  const res = await $vue.api.getContent({ key: val })
  data.content = res
}

After:

const inputEvent = {
  change: setData
}

async function setData(val) {
  if (val) {
    const res = await $vue.api.getContent({ key: val })
    data.content = res
  } else {
    data.content = ''
  }
}

9、多个异步任务同时运行

Before:

逐个运行,假设接口A耗时2秒,接口B耗时3秒,该方法总计等待时长约5秒

async function getData(val) {
  const params = { key: val }
  const res1 = await $vue.api.getContent1(params)
  const res2 = await $vue.api.getContent2(params)
  if (res1 && res2) {
    // code
  }
}

After:

同时运行,该方法只等待最长响应时长接口B的3秒

async function getData(val) {
  const params = { key: val }
  const [res1, res2] = await Promise.all([
    $vue.api.getContent1(params),
    $vue.api.getContent2(params)
  ])
  if (res1 && res2) {
    // code
  }
}

10、使用别名方式引入资源(Vue)

针对层级过多的路径

<template>中的资源

Before:

<img src="../../../assets/images/empty.png">

After:

<img src="@/assets/images/empty.png">

<script>中的资源

Before:

import attachmentList from '../../../views/common/attachmentList'

After:

import attachmentList from '@/views/common/attachmentList'

<style>中的资源

Before:

.text-underline {
  background-image: url('../../../assets/images/empty.png');
}

After:

.text-underline {
  background-image: url('~@/assets/images/empty.png');
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容