zoukankan      html  css  js  c++  java
  • JavaScript数组方法--reduce、reduceRIght、reverse

      今天写的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
        }





  • 相关阅读:
    011 处理模型数据时@ModelAttribute的使用
    动态产生DataSource------待整理
    连接池问题
    maven加载第三方jar不能加载
    010 处理模型数据(ModelAndView,Map Model,@SessionAttributes)
    009 使用servlet API作为参数
    008 使用POJO对象绑定请求参数
    007 @CookieValue绑定请求中的cookie
    006 请求处理方法签名
    005 RequestMapping_HiddenHttpMethodFilter 过滤器
  • 原文地址:https://www.cnblogs.com/zhuhuoxingguang/p/10670457.html
Copyright © 2011-2022 走看看