今天写的reduce是比较复杂的一个数组方法,其实在这之前我也用过reduce,可是每次用起来总感觉不那么顺手,主要还是因为不熟,对reduce本身不熟。首先reduce这个单词翻译为中文,不那么直观,再加上他的示例比较简单,导致用在复杂情况下,就有点懵逼的感觉。通过自己的理解,我们重构一次,可能更能够方便理解!

  • reduce:reduce() 方法对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。
    看到MDN给的这句解释,可能就懵了!
    什么叫reducer函数?为什么升序执行?
    我们直接看示例吧(虽然他的示例简单了点)!

    const array1 = [1, 2, 3, 4];
    const reducer = (accumulator, currentValue) => accumulator + currentValue;
    console.log("不提供初始化的值:" + array1.reduce(reducer));
    console.log("初始化值为5:" + array1.reduce(reducer, 5));

      
    看结果:

    似乎隐隐约约明白点什么了,但是又不那么清晰!那好,我们继续!
    语法:

    arr.reduce(callback[, initialValue])
    

      接受一个回调函数callback:执行数组中每个值的函数,包含四个参数:
      

    一个可选的初始化的值initialValue:作为第一次调用 callback函数时的第一个参数的值。 如果没有提供初始值,则将使用数组中的第一个元素。 在没有初始值的空数组上调用 reduce 将报错。

    到这里,如果还是没怎么明白的话,简单翻译一下,就是reduce方法对数组中的每个元素顺序执行一遍回调函数。用上例来说就是,将数组array1中元素在initialValue的基础上累加,如果没有提供initailValue,默认值为array1[1]。
    再看上面的两次调用:

    console.log("不提供初始化的值:" + array1.reduce(reducer));

    第一次没有初始值,那就是数组中元素求和。

    console.log("初始化值为5:" + array1.reduce(reducer, 5));  

    这一次initailValue为5,那就是所有元素求和加上5。
    再来一次稍微复杂点的示例吧!

    const persons = [{name: 'zhang', age: 12}, {name: 'leo', age: 32}, {name: 'gre', age: 21}];

    选取persons当中年龄最大的元素!

    let person = persons.reduce(function(current, item){
    return item.age > current.age ? item : current
    })
    console.log(person)

    我们按照上面解释的reduce对照理解一下需求和代码,就是persons数组当中选取出age值最大的元素。
    而我们的person是怎么执行的呢,一个累计器current,计算到当前元素时,age最大的元素,第一次执行,没有提供初始值,那默认初始值为persons[0]。与自身比较不管是什么结果,都返回persons[0]。第二次执行,用persons[1]与persons[0]比较,返回persons[1]。再用persons[1]与persons[2]比较,依然返回persons[1]。
    似乎有点明白了。
    好,再来一个需求,计算所有元素age的和。

    let age = persons.reduce(function(current, item){
    return typeof current !== 'number'? (item.age+ current.age) : item.age + current
    })

    当你自己写一遍的时候,会发现总会有各种各样的问题。原因在哪呢?
    关键点:如果没有初始化值,那默认的初始化值是数组的第一个元素。看出来了吗?我们这里没有提供初始化值,所以默认初始化值是persons[0]。所以最开始的累计器是一个对象{},而我们实际上需要返回的是一个数字(所有年龄求和),所以说当结果类型与元素类型不一致,同时你又没有传递初始化值,那么就只能说自己坑自己了。最简单的方法,其实是在这里传递一个初始化的值0.

    let age = persons.reduce(function(current, item){
    return item.age + current
    },0)

    依然懵逼。。。
    好吧,算了,重构一下吧!

    function reduce (arr, fn, initialValue) {
    if (!(arr instanceof Array)) throw new Error("请确保第一个参数类型为数组")
    var accumulator = initialValue !== undefined ? initialValue : arr[0]
    var j = initialValue !== undefined ? 0 : 1
    for (var i = j; i < arr.length; i++) {
    accumulator = fn(arr[i], accumulator, i + j, arr)
    }
    return accumulator
    }

    看这一小段代码,再回头理解累计器accumulator和初始化值initialValue。对照前面的说法,再来理解reduce方法。

  • reduceRight:reduceRight() 方法接受一个函数作为累加器(accumulator)和数组的每个值(从右到左)将其减少为单个值。
    看名称,与reduce方法应该就没有特别大的区别,只不过reduce升序(从左到右),而当前这个reduceRight降序(从右到左),直接重构吧。
    function reduceRight (arr, fn, initialValue) {
    if (!(arr instanceof Array)) throw new Error("请确保第一个参数类型为数组")
    var len = arr.length, accumulator = initialValue
    if (initialValue === undefined) {
    len = arr.length - 1
    accumulator = arr[len]
    }
    while (len) {
    accumulator = fn(arr[len - 1], accumulator, len - 1)
    len--
    }
    return accumulator
    }

    其实比较方便的方法,是对照reduce的for循环,从最后一个元素向前。

  • reverse:reverse() 方法将数组中元素的位置颠倒,并返回该数组。该方法会改变原数组。
    reverse还是比较简单的,从字面理解就是相反,也就是数组变成倒序,需要注意的是会改变原数组,也比较常见,直接重构!

    function reverse (arr) {
    if (!(arr instanceof Array)) throw new Error("请确保参数类型为数组")
    var i = Math.ceil(arr.length / 2)
    for (var j = 0; j < i; j++) {
    var temp = arr[j]
    arr[j] = arr[arr.length - j - 1]
    arr[arr.length - j - 1] = temp
    }
    return arr
    }

JavaScript数组方法--reduce、reduceRIght、reverse的更多相关文章

  1. JavaScript数组方法reduce解析

    Array.prototype.reduce() 概述 reduce()方法是数组的一个实例方法(共有方法),可以被数组的实例对象调用.reduce() 方法接收一个函数作为累加器(accumulat ...

  2. 几个关于js数组方法reduce的经典片段

    以下是个人在工作中收藏总结的一些关于javascript数组方法reduce的相关代码片段,后续遇到其他使用这个函数的场景,将会陆续添加,这里作为备忘. javascript数组那么多方法,为什么我要 ...

  3. Javascript中数组方法reduce的妙用之处

    Javascript数组方法中,相比map.filter.forEach等常用的迭代方法,reduce常常被我们所忽略,今天一起来探究一下reduce在我们实战开发当中,能有哪些妙用之处,下面从red ...

  4. JavaScript数组方法之reduce

    又见到数组方法了,在前面已经的多次写到过数组方法,甚至都使用原生方法重构了一遍数组的各个方法,可是随着数组方法reduce的应用,发现reduce真的是妙用无穷啊!还是很值得再拿出来说一遍的. 我们再 ...

  5. JavaScript数组方法大全(推荐)

    原网址:http://www.jb51.net/article/87930.htm 数组在笔试中经常会出现的面试题,javascript中的数组与其他语言中的数组有些不同,为了方便之后数组的方法学习, ...

  6. JavaScript数组方法详解

    JavaScript数组方法详解 JavaScript中数组的方法种类众多,在ES3-ES7不同版本时期都有新方法:并且数组的方法还有原型方法和从object继承的方法,这里我们只介绍数组在每个版本中 ...

  7. JavaScript数组方法大集合

    JavaScript数组方法集合 本文总结一下js数组处理用到的所有的方法.自己做个笔记. 数组方法 concat() 合并两个或多个数组 concat()能合并两个或者多个数组,不会更改当前数组,而 ...

  8. 一站式超全JavaScript数组方法大全

    一站式JavaScript数组方法大全(建议收藏) 方法一览表 详细操作 本人总结了JavaScript中有关数组的几乎所有方法(包含ES6之后新增的),并逐一用代码进行演示使用,希望可以帮助大家! ...

  9. 【译】你应该了解的JavaScript数组方法

    让我们来做一个大胆的声明:for循环通常是无用的,而且还导致代码难以理解.当涉及迭代数组.查找元素.或对其排序或者你想到的任何东西,都可能有一个你可以使用的数组方法. 然而,尽管这些方法很有用,但是其 ...

随机推荐

  1. go接口

    // 接口例子package main import "fmt" type Human struct { Name string Age int Sex string Phone ...

  2. NoSQL、memcached介绍、安装memcached、查看memcached状态

    1.NoSQL 2.memcached介绍     3.安装memcached(二进制包安装) yum install -y memcached libmemcached libevent (若没有安 ...

  3. 【译著】Code First :使用Entity. Framework编程(5)

    第五章 对数据库映射使用默认规则与配置 到目前为止我们已经领略了Code First的默认规则与配置对属性.类间关系的影响.在这两个领域内,Code First不仅影响模型也影响数据库.在这一章,你将 ...

  4. 653. Two Sum IV - Input is a BST-easy

    我不懂有没有收藏之类的功能,收藏别人的解法. tql,不懂为什么直接比较set里的值,不是两个数sum么 有一些答案都用到了iterator迭代器 http://www.cplusplus.com/r ...

  5. Appium环境搭建——安卓模拟器(AVD)调试 2-运行Apk失败点的总结

    如何优化AVD模拟器运行速度? 解决方法:开启IntelHAXM 查询intelhaxm是否已经开启: sc query intelhaxm 若开启成功,则如图所示 若没有开启,可以通过BIOS打开, ...

  6. SP3871 GCDEX - GCD Extreme

    //author Eterna #define Hello the_cruel_world! #pragma GCC optimize(2) #include<iostream> #inc ...

  7. Linux第十一节课学习笔记

    区域就是firewalld预先准备了几套防火墙策略集合(策略模板),用户可以根据生产场景的不同而选择合适的策略集合,从而实现防火墙策略之间的快速切换. RUNTIME模式:当前生效,重启失效:PERM ...

  8. Android游戏引擎总汇 原文出处:http://software.intel.com/en-us/blogs/2012/03/13/game-engines-for-android?page=1

    随着Android系统的使用越来越广泛,了解一下Android平台下的游戏引擎就非常有必要.而同时因为基于Intel x86的移动设备越来越多,我也非常关注支持x86的移动游戏引擎.然而就目前为止游戏 ...

  9. VirtualBox虚拟机禁止时间同步

    某机器为客户提供,宿主机时间快了20分钟,导致虚拟机时间也跟着快20分钟,每次更改完虚拟机时间,不到1分钟时间又变回去了 在一些情况下必须让VirtualBox虚拟客户机的时间和主机不同步,百度了一番 ...

  10. 注册Docker Hub、以及Push(九)

      一.注册   1.使用浏览器打开官网的时候,发现注册按钮点不了       2.下载google访问助手,添加到浏览器         下载地址:http://www.ggfwzs.com/,根据 ...