jsArray常用API之替代传统fori循环

前言

先看看下面这段代码:(重点关注两函数的实现方式,无需细看实现逻辑)

function getAreaSale1(values, areas) {
  const areaSale = [];
  areas.forEach(area => {
    let sum = values.reduce((acc, cur) => {
      if (cur.area === area) {
        acc[area] === undefined ? acc[area] = cur.sale : acc[area] += cur.sale;
      }
      return acc;
    }, {});
    areaSale.push(sum);
  })
  return areaSale;
}

function getAreaSale2(values, areas) {
  const areaSale = [];
  for (let i = 0; i < areas.length; i++) {
    let sum = {};
    for (let j = 0; j < values.length; j++) {
      if (values[j].area === areas[i]) {
        sum[areas[i]] === undefined ? sum[areas[i]] = values[j].sale : sum[areas[i]] += values[j].sale;
      }
    }
    areaSale.push(sum);
  }
  return areaSale;
}

function main() {
  const values = [
    {
      area: '西安',
      sale: 123
    },
    {
      area: '咸阳',
      sale: 234
    },
    {
      area: '西安',
      sale: 345
    },
    {
      area: '宝鸡',
      sale: 456
    },
    {
      area: '铜川',
      sale: 567
    },
    {
      area: '铜川',
      sale: 678
    },
    {
      area: '宝鸡',
      sale: 789
    },
  ]

  const areas = ['西安', '咸阳', '宝鸡', '铜川'];
  console.log(getAreaSale2(values, areas));
}

getAreaSale1函数与getAreaSale2函数的功能一模一样,只不过getAreaSale1函数显得更加有格调一些。
不知道大家有发现没,那些大佬以及源码里所产出的代码里很难看到传统的fori循环,所以本篇博客就是教你如何使用Array中的现有API取代传统的fori循环,从而让自己的代码看起来更像“源码”!
也许这些API的性能不及传统的fori循环高效,但是在绝大多数情况下是相差无几。换句话说,很多时候明明可以使用API简单处理的问题而自己却使用fori循环去实现此API的部分功能来解决问题,此做法就是变相重复造轮子。

正文

以下所有API的讲解我都会结合具体示例并对比传统fori循环进行叙述。
并且为了让大家对于API更有源码的直观感,以下所有的API内部函数的调用我都使用箭头函数的方式。

foreach

foreach可以简单的理解为原始fori的API版本,遍历数组中的每个元素并在回调函数中执行自己的逻辑代码,无返回值。
foreach使用方式:

arr.forEach(callback(currentValue [, index [, array]])[, thisArg])

show you my example:

const arraySparse = [1, 3, 8, 7];

arraySparse.forEach(element => console.log(element));

function foreach(arraySparse) {
  for (let i = 0; i < arraySparse.length; i++) {
    console.log(arraySparse[i]);
  }
}

every

every基于遍历所有数组元素的基础上,并判断其所有元素是否都能通过某个指定函数的测试,结果返回一个布尔值。
every的使用方式:

arr.every(callback(element[, index[, array]])[, thisArg])

show you my example:

const arraySparse = [1, 3, 8, 7];

const result = arraySparse.every(element => element <= 8);

function every(arraySparse) {
  for (let i = 0; i < arraySparse.length; i++) {
    if (arraySparse[i] > 8) {
      return false;
    }
  }
  return true;
}

filter

filter方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素,不改变原数组内容。
filter的使用方式:

const newArray = arr.filter(callback(element[, index[, array]])[, thisArg])

show you my example:

const arraySparse = [1, 3, 8, 7];

const filterArray = arraySparse.filter(element => element > 5);

function filter(arraySparse) {
  const filterArray = [];
  for (let i = 0; i < arraySparse.length; i++) {
    if (arraySparse[i] > 5) {
      filter.push(arraySparse[i]);
    }
  }
  return filterArray;
}

find

find方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined。
find的使用方式:

arr.find(callback[, thisArg])

show you my example:

const arraySparse = [1, 3, 8, 7];

const findArray = arraySparse.find(element => element > 5);

function find(arraySparse) {
  for (let i = 0; i < arraySparse.length; i++) {
    if (arraySparse[i] > 5) {
      return arraySparse[i];
    }
  }
  return undefined;
}

map

map方法创建一个新数组,其结果是该数组中的每个元素是调用一次提供的函数后的返回值,不改变原数组内容。
map的使用方式:

var new_array = arr.map(function callback(currentValue[, index[, array]]) {
 // Return element for new_array 
}[, thisArg])

show you my example:

const arraySparse = [1, 3, 8, 7];

const mapArray = arraySparse.map(element => element + 5);

function map(arraySparse) {
  const mapArray = [];
  for (let i = 0; i < arraySparse.length; i++) {
    mapArray.push(arraySparse[i] + 5);
  }
  return mapArray;
}

some

some方法测试数组中是不是至少有1个元素通过了被提供的函数测试。它返回的是一个Boolean类型的值。
some的使用方式:

arr.some(callback(element[, index[, array]])[, thisArg])

show you my example:

const arraySparse = [1, 3, 8, 7];

const someArray = arraySparse.some(element => element > 8);

function some(arraySparse) {
  for (let i = 0; i < arraySparse.length; i++) {
    if (arraySparse[i] > 8) {
      return true;
    }
  }
  return false;
}

注:some方法和every方法恰好相反。

reduce

reduce方法对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。
reduce的使用方式:

arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])

show you my example:

const arraySparse = [1, 3, 8, 7];

const reduceArray = arraySparse.reduce((acc, cur) => acc + cur, -1);

function reduce(arraySparse, index) {
  let acc = index;
  for (let i = 0; i < arraySparse.length; i++) {
    const cur = arraySparse[i];
    acc += cur;
  }
  return acc;
}

小结

上述7种API都有回调函数的功能,其实这个回调函数的代码就是fori循环里的逻辑代码,比如foreach,只不过更多的API相对于fori循环已经帮助我们实现了特定的逻辑代码。看完上述7种API与fori的案例对比,是不是瞬间感觉自己制造了不少重复的轮子。
上述讲述时所给出的案例都是一些最基本的单一应用案例,复杂的案例也不过是换汤不换药,比如文中最开始给的案例,使用foreach+reduce取代fori循环。
最后,熟练掌握这7种API就足矣替代90%及其以上情形的fori循环,至于剩下10%的情形也不是因为无法替代而是使用传统的fori循环效率明显会更高,比如如下的这个案例:

function main() {
 const values = [
    {
      area: '西安',
      sale: 123
    },
    {
      area: '咸阳',
      sale: 234
    },
    {
      area: '宝鸡',
      sale: 456
    },
    {
      area: '铜川',
      sale: 567
    },
    {
      area: '西安',
      sale: 345
    },
    {
      area: '咸阳',
      sale: 890
    },
    {
      area: '宝鸡',
      sale: 789
    },
    {
      area: '铜川',
      sale: 678
    },
  ]
  const areas = ['西安', '咸阳', '宝鸡', '铜川'];
}

稍微更改一下最开始那个案例的数据,只不过这次我想要得到的是如下的结果:

const result = [
    [
      {
        area: '西安',
        sale: 123
      },
      {
        area: '西安',
        sale: 345
      }
    ],
    [
      {
        area: '咸阳',
        sale: 234
      },
      {
        area: '咸阳',
        sale: 890
      }
    ],
    [
      {
        area: '铜川',
        sale: 567
      },
      {
        area: '铜川',
        sale: 678
      }
    ],
    [
      {
        area: '宝鸡',
        sale: 456
      },
      {
        area: '宝鸡',
        sale: 789
      }
    ]
  ]

此时这种case的数据使用传统的fori循环进行处理效果明显更高,至于原因应该不难想到。

结语

到此,本篇博客的内容就叙述完毕,正文并没有详细的讲解此API的用法,重点在于API与fori循环的使用对比,如果有对API使用有疑惑的朋友,可以参看mdn官方文档进行API学习:Array API使用文档
相信看完本篇博客之后的朋友能够对此类API的使用更加熟练,希望日后每当要使用fori循环时能够第一时间思考到是否可以使用API进行问题处理,从而使自己的代码观感更上一层楼。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值