首页 > 代码库 > Using Array.prototype.reduce() to Reduce Conceptual Boilerplate for Problems on Arrays

Using Array.prototype.reduce() to Reduce Conceptual Boilerplate for Problems on Arrays

以下内容转自FreeCodeCamp:Using Array.prototype.reduce() to Reduce Conceptual Boilerplate for Problems on Arrays

Using Array.prototype.reduce() to Reduce Conceptual Boilerplate for Problems on Arrays译:使用Array.prototype.reduce()可以减少数组循环等繁琐问题

  我们知道,for循环在javascript里面,是不精炼的。它会让你占用你的时间:缓存占用 、命名和逻辑错误。并且,写代码时,不用闭包循环钟的异步的过程代码会出现错误。见:Asynchronous Process inside a javascript for loop

  这个标题已经告诉我们:你可以用reduce()方法去解决与数组相关的问题,而不是用for循环或者while循环。如果你希望继续读下去:首先要知道什么时“递归”和一些比较有用的数组方法Array.prototype.map() 或 Array.prototype.filter()。

  实践大于真知。我们一起看看怎么习惯使用reduce()。需先提示:在学习之前确保你是来学习解决问题的,而不是匆匆一瞥。

 


 

Can I Reduce Any Array-related Problem?我能解决任何与数组相关的问题吗?

  是的,可以!事实上,不仅仅能解决数组相关的问题,只要他是个问题,就可以解决。例如,创建一个很常见的链接地址标题:slug url,来自新闻、博客、甚至是问答论坛的大字标题。

function createSlug(str){  return str.split(" ").reduce(function(prev, next){    return prev.concat([next.toLowerCase()]);//That‘s the core of the functionality we want.  }, [])  .join("-");}

自己测试一下在控制台,例如“Leo Finally Wins a Freaking Oscar!”

leo-finally-wins-a-freaking-oscar!

 

But I Do NOT Understand Reduce At All!但是我根本不了解Reduce!!

  好吧,不要害怕!在接下来的几分钟,你即将成为一个Reduce忍者。

  每个JavaScript函数都有三件事你需要知道,理解函数是如何工作的:

  • The input
  • The output
  • The execution context

  是的,我可以看到你在新标签页中打开官方MDN文档!没关系,先读到这。我是认真的,这不是笑话。

  Array.prototype.reduce()有两个参数:回调函数和初始值,都为输入参数。(初始值是很重要的。很多开发人员忘记提供初始值正确,最后搞砸了他们的代码)。

arr.reduce(function(){}, initialValue);//假设 arr 是一组随机数组。

 

  现在,让我们仔细看看回调函数,也就是reduce()第一个参数,这个回调需要两个参数。在官方文档中,这两个的两个参数称为prev和next。就我个人而言,我不认为这两个参数的名称能代表这个参数本来的意义。

  我把回调函数的第一个参数称为‘acc’,代表累计值(accumulated value);‘item’,代表当前被访问值。所以,我们的reduce()就像下面一样:

arr.reduce(function(acc, item){ /* here you have to complete the function */}, initialValue);

  我们前面提到过,reduce()接送一个函数作为累加器。我们来看看这些‘acc’和‘item’的值将会怎么变化。

var arr = [10, 20, 30, 60];arr.reduce(function(acc, item){   console.log(acc, item);}, 0);

  在浏览器或节点控制台执行上述会给你这个作为输出:

0 10undefined 20undefined 30undefined 60

  注意这些输出的数字,和数组[10, 20, 30, 60]的数字元素一样。实际上,reduce()把数组的元素打印出来了。

  因此,我们可以推断出reduce()需要您的自定义回调并执行数组的每个元素。虽然这样做,它使当前项可用于自定义回调为‘item’参数。

  但是acc呢?我们看到,除了第一行,当‘item’= 10,它是‘undefined’。在第一行,对应于第一个迭代iteration,它的值和初始值initialvalue,0,一样。

   简而言之,我们的‘acc’是累加器,而不是正在累加中的值!但是,我们如何积累?让我们尝试执行: 

var arr = [10, 20, 30, 60];arr.reduce(function(acc, item){   console.log(acc, item);   return acc;}, 0);

  这一次,输出的变化:

0 100 200 300 60

 

  正如您可以看到,‘acc’会保持不变的值。预计,我们不改变‘acc’在自定义回调的值。我们返回任何reduce()使得可用在给定迭代。

  但是我们意识到什么,‘acc’为当前重复的值,将从自定义回调返回值从先前的重复工作。最终,重复工作结束后,返回的‘acc’的最终值将reduce()。

  这使得只有一个重要的部分在我们的理解——执行上下文的价值,或者‘this’!所以,我们再次的方法我们的朋友,JS控制台和执行:  

var arr = [10, 20, 30, 60];arr.reduce(function(acc, item){   console.log(acc, item, this);   return acc;}, 0);

 

  如果在严格模式下,则用这个:

var arr = [10, 20, 30, 60];arr.reduce(function(acc, item){   console.log(acc, item, this);   return acc;}.bind(arr), 0);

  我已经绑定arr数组本身,但是你可以将它设置为在您的环境中任何对象。


Understanding Reduce 理解reduce

 

   我们来总结一下reduce函数的简单参考:

  • reduce减少需要一个自定义回调作为它的第一个参数,和一些初始值作为第二个参数。
  • 重要的是我们不要忘记第二个参数,初始值,我们显式地设置在使用它。
  • 自定义回调函数的输入参数是累积值‘acc’;和数组的当前项,‘item’。
  • 在当前迭代,在下一个迭代中‘acc’的值将返回值在回调。
  • 使用reduce()的重要点是:正确的形成‘acc’,返回最终的函数调用。

 

Using Reduce

  让我们开始一个简单的数组操作,找到数组中最大的值。为了简便起见,我假设这是一个整数数组中。

  为了形成一个解决方案,我们需要考虑如何形成‘acc’的reduce让我们回调,遍历该数组。一个想法我觉得有用,是想到loop-invariants。我们要想出一个方方法,无论什么数组的大小或内容,‘acc’应该总是最大值。

  我的数组是[20, 50, 5, 60]。经过两次迭代后,‘item’将是 5,‘acc’应该是max(20, 50) = 50。

var arr = [20, 50, 5, 60];arr.reduce(function(acc, item){  return Math.max(acc, item);}, 0);

它可能容易重写如下,与函数式编程的原则:

var arr = [20, 50, 5, 60];arr.reduce(Math.max, 0);

 

Using Array.prototype.reduce() to Reduce Conceptual Boilerplate for Problems on Arrays