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 10
undefined 20
undefined 30
undefined 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 10
0 20
0 30
0 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);
时间: 2024-11-07 11:08:36

Using Array.prototype.reduce() to Reduce Conceptual Boilerplate for Problems on Arrays的相关文章

Array.prototype.reduce

[Array.prototype.reduce] Array.reduce([callback, initialValue]) 参数 callback 执行数组中每个值的函数,包含四个参数: previousValue 上一次调用回调函数返回的值,或者是提供的初始值(initialValue) currentValue 数组中当前被处理的元素 currentIndex 当前被处理元素在数组中的索引, 即currentValue的索引.如果有initialValue初始值, 从0开始.如果没有从1

01 - Execise About Array.prototype.reduce()

Description: Write a generic function chainer Write a generic function chainer that takes a starting value, and an array of functions to execute on it (array of symbols for ruby). The input for each function is the output of the previous function (ex

JavaScript,通过分析Array.prototype.push重新认识Array

在阅读ECMAScript的文档的时候,有注意到它说,数组的push方法其实不仅限于在数组中使用,专门留作通用方法.难道是说,在一些类数组的地方也可以使用?而哪些是和数组非常相像的呢,大家或许一下子就可以想到就是Object对象.因为Array就是继承自Object的,可以用 [] instanceof Object,会发现返回的是true.当然大家都知道,这也不是什么新鲜事.那我们可以大胆尝试一下,如果我们将数组的push方法应用在对象上,会一个怎么样的表现呢? 我们通过call,将this的

使用Array.prototype.indexOf()的几点注意

对应indexOf这个方法,在日常开发中比较常见的应该是String.prototype.indexOf()方法,Array.prototype.indexOf()方法和其有很大的相似性,本文不想去描述其的基本用法,而是去探究在使用中需要考虑的一些问题. 一.性能 在数组元素少的情况下,我们虽然只是跳过一个元素来检索,性能微不足道,但是当我们正在处理数以千计的元素,如果使用indexOf()的第二个参数,你可能获得性能上的显著提升. 二.全等(===) indexOf方法使用全等(===)来判断

数组方法 Array.prototype

Object.prototype 数组的值是有序的集合,每一个值叫做元素,每一个元素在数组中都有数字位置编号,也就是索引,js中数组是弱类型的,数组中可以含有不同类型的元素.数组元素甚至可以是对象或者其他数组 长度范围:1====2的23方-1 new Array(100)//undifind*100 arr[5]=10; arr.length//6 push() unshift() shift() pop() var Arr=[1,true,undifind,{x:1},[1,2,3]]; A

数组的方法之(Array.prototype.forEach() 方法)

forEach() 方法对数组的每个元素执行一次提供的函数. 注意: 没有返回一个新数组 并且 没有返回值! 应用场景:为一些相同的元素,绑定事件处理器! const arr = ['a', 'b', 'c']; arr.forEach(function(element) { console.log(element); }); arr.forEach( element => console.log(element)); 语法 callback为数组中每个元素执行的函数,该函数接收三个参数: cu

Array 和 Array.prototype

定义 Array 对象是用于构造数组的全局对象,数组是类似于列表的高阶对象. Array.prototype 属性表示Array构造函数的原型,并允许您向所有Array对象添加新的属性和方法. 获取相应的属性名称 Object.getOwnPropertyNames(Array) //[ "length", "name", "prototype", "isArray", "from", "of&q

将函数的实际参数转换成数组的方法,习惯用Array.prototype.slice.call(arguments)

实际参数在函数中我们可以使用 arguments 对象获得 (注:形参可通过 arguments.callee 获得),虽然 arguments 对象与数组形似,但仍不是真正意义上的数组. 我们可以通过数组的 slice 方法将 arguments 对象转换成真正的数组. 方法一:通过Array.prototype属性调用slice方法 var args = Array.prototype.slice.call(arguments); Array 本身是没有 slice 方法,它的方法在 Arr

(转)Array.prototype.slice.call自解

很多框架或者库里面都会有这句的使用,最多的还是通过Array.prototype.slice.call(arguments,0)把arguments这个伪数组转换为真正的数组.但为什么可以这么做,却一直是半懂不懂的.昨天晚上看了mootools的源码,google了一下,终于彻底明白了. call方法的作用就不用多说了,Array.prototype.slice.call(arguments,0)就类似于arguments.slice(0),但因为arguments不是真正的Array,所以它没