减少代码中的for循环

(优化代码)

Posted by YC on December 9, 2018

在js代码中消除for循环以及降低if else 代码复杂度

个人认为for循环不够语义化,单单一个循环无法看懂这个函数的作用,而一些js自带的api能帮助更好的理解,例如数组的everysome,对于一个数组,使用every就能够满足数组里元素如果都满足判断函数就返回true,如果存在不满足就返回false,这比自己写for循环的可读性大大提高,当然,for循环的自由度高,能写任何遍历的方法,而这些api接口则对应特定的需求。

用filter, map, 和 其他es6高阶遍历函数

  • 🌰1:将数组中的false值去除
const arr = [3, 4, 5, 2, undefined, null, 0, ""]
// 使用过滤函数,过滤出数组元素满足回调的函数的值
const compact = arr => arr.filter(Boolean)

Array.prototype.filter() mdsn文档

  • 🌰2: 将数组中的VIP用户余额加 10
const users = [
  { username: "Kelly", isVIP: true, balance: 20 },
  { username: "Tom", isVIP: false, balance: 19 },
  { username: "Stephanie", isVIP: true, balance: 30 }
]

users.map(
  user => (user.isVIP ? {...user, balance: user.balance + 10} : user)
)

Array.prototype.map() mdsn文档

  • 🌰3: 判断字符串中是否含有元音字母(判断是否存在一个)
const someString = "asdfghjkl"

//写法一
const has = [...someString].some(char => {
  return ["a", "e", "o", "i", "u"].includes(char)
})

//写法二
const isVowel = char => ["a", "e", "o", "i", "u"].includes(char)

const hasVowel = str => [...str].some(isVowel)

hasVowel(someString)

Array.prototype.some() mdsn文档

  • 🌰4: 判断用户是否全部是未成年(判断元素是否全部成立)
const users = [
  { name: "Jim", age: 23 },
  { name: "Lily", age: 17 },
  { name: "Will", age: 25 }
]
// 便利 users 如果user.age都大于18 则返回true 
users.every(user => user.age >= 18)

Array.prototype.every() msdn文档

  • 🌰5 找出用户第一个未成年的人(查找出数组中第一个满足条件的人)
const users = [
  { name: "Jim", age: 23 },
  { name: "Lily", age: 17 },
  { name: "Will", age: 25 }
]

const findTeen = (users) => {
    return users.find(user => user.age < 18)
} 
// 返回第一个满足条件的元素
findTeen(users)
// { name: "Lily", age: 17 }

Array.prototype.find() msdn文档

  • 🌰6 数组中去重
const dupArr = [1, 2, 3, 3, 3, 3, 6, 7]
// 利用集合没有重复元素的特性对数组去重
const uniq = arr => [...new Set(arr)]
uniq(dupArr)
  • 🌰7: 随机整数数组
const getNumArr = (length, limit) => {
    return Array.from({length}, _ => Math.floor(Math.random() * limit))
}
getNumArr(10, 100)

Array.from() msdn文档

  • 🌰8: 将多层数组转换为一层数组(将数组剥离)
const nestedArr = [1, 2, [3, 4, [5, 6]]]
const flatten = arr =>
  arr.reduce(
    (flat, next) => flat.concat(Array.isArray(next) ? flatten(next) : next),
    []
  )
  //利用reduce的累加器 将数组累加计算
flatten(nestedArr)

Array.prototype.reduce() msdn文档

  • 🌰9: 将下面数组转成对象,key/value 对应里层数组的两个值
const objLikeArr = [["name", "Jim"], ["age", 18], ["single", true]]

const fromPairs = pairs =>
  pairs.reduce(
  (res, pair) => ((res[pair[0]] = pair[1]),
   res), {})
fromPairs(objLikeArr)

对于简单的if... if... 类型,可以将单块的if语句进行拆分为一个函数

🌰:

if (...) {
    if () {...}
    if () {...}
}
if (...) {
    if () {...}
    if () {...}
}
if (...) {
    if () {...}
    if () {...}
}
//可以拆分为3块函数
function A () {
    if (...) {
        if () {...}
        if () {...}
    }
}
function B () {
    if (...) {
        if () {...}
        if () {...}
    }
}
  • 这样的拆分能使代码可读性更高,将分装的函数名命名语意化的名字,维护的时候只要看到函数名,就明白这段if语句是什么作用

对于else if语句的代码,在几个执行函数中选择一个进行执行的函数

Image text

  • 自己定一个查找表,根据处理函数判断条件来进行不同的操作
const rules = {
  x: (a, b, c) => {...},
  y: (a, b, c) => {...},
  z: (a, b, c) => {...}
}

function test (a, b, c) {
    const action  = determineAction(a, b, c)
    return rules[action](a, b, c)
}
function determineAction (a, b, c) {
    if (...) {
        return 'x'
    } else if (...) {
        return 'y'
    } else if () {
        return 'z'
    }
}

//第二种方式
const rules = [
  {
    match: function (a, b, c) { ... },
    action: function (a, b, c) { ... }
  },
  {
    match: function (a, b, c) { ... },
    action: function (a, b, c) { ... }
  },
  {
    match: function (a, b, c) { ... },
    action: function (a, b, c) { ... }
  }
]
function test (a, b, c) {
  for (let i = 0; i < rules.length; i++) {
    if (rules[i].match(a, b, c)) {
      return rules[i].action(a, b, c)
    }
  }
}

单条if语句

  • 业务中会用到很多if语句,就执行一行函数的处理例如:
var sum = 0
if (typeof a === 'Number') {
    sum += a
}
  • 对于这样的代码,可以通过&&进行处理
(typeof a === 'Number') && (sum +=a)

总结

  • 这些代码写法其实在功能上,和原来的没有区别,只是在代码的可读性上能更好,更加方便我们个人维护。