Array.prototype.reduce has not been used much in the past. I asked this question in the byteDance interview, and then I went to see MDN to understand it a little bit

usage

The reduce method passes each element of the array from left to right in turn to the callback function

👇 are some of the common places

Counts the number of occurrences of each character in a string

Method 1 (this is the most common method I use without array.prototype.reduce):

   const str = '9kFZTQLbUWOjurz9IKRdeg28rYxULHWDUrIHxCY6tnHleoJ'
   const obj = {}
   str.split(' ').forEach(item= > {
       obj[item] ? obj[item]++ : obj[item] = 1
   })
Copy the code

Method 2 (this is a little fun 🤪):

  const str = '9kFZTQLbUWOjurz9IKRdeg28rYxULHWDUrIHxCY6tnHleoJ'
  const obj = {}
  Array.from(str).reduce((accumulator, current) = > {
    current in accumulator ? accumulator[current]++ : accumulator[current] = 1
    return accumulator  
  }, obj)
Copy the code

Well, method 2 although the steps are more complicated than method 1 (actually not complicated roar), but is it more fun 😉?

Filters data in an array that meets multiple criteria at once

Method 1 (Common):

   const arr = [
      {
        "name": "a1111"."age": 25
      },
      {
        "name": "a1"."age": 26
      },
      {
        "name": "a11"."age": 27
      },
      {
        "name": "a"."age": 29
      },
      {
        "name": "a11"."age": 29
      },
      {
        "name": "a11"."age": 26
      },
      {
        "name": "a111"."age": 25
      },
      {
        "name": "a11"."age": 26
      },
      {
        "name": "a1"."age": 26
      },
      {
        "name": "a"."age": 26
      }
    ]
    
    arr.filter(item= > item.name.length === 3)
       .filter(item= > item.age > 26)
    /* [ { "name": "a11", "age": 27 }, { "name": "a11", "age": 29 } ] */
Copy the code

Method 2 Reduce method (thanks for @Zhanggenming’s proof, modified):

    const arr = [
      {
        "name": "a1111"."age": 25
      },
      {
        "name": "a1"."age": 26
      },
      {
        "name": "a11"."age": 27
      },
      {
        "name": "a"."age": 29
      },
      {
        "name": "a11"."age": 29
      },
      {
        "name": "a11"."age": 26
      },
      {
        "name": "a111"."age": 25
      },
      {
        "name": "a11"."age": 26
      },
      {
        "name": "a1"."age": 26
      },
      {
        "name": "a"."age": 26}]const filter1 = (arr) = > arr.filter(item= > item.name.length === 3)
    const filter2 = (arr) = > arr.filter(item= > item.age > 26)
    const fnArr = [filter1, filter2]
    fnArr.reduce((accumulator, fn) = > {
     accumulator = fn(accumulator)
     return accumulator
    }, arr)
   /* [ { "name": "a11", "age": 27 }, { "name": "a11", "age": 29 } ] */
Copy the code

With this approach, let’s try implementing array.prortotype.reduce with a for loop

Let’s look at the parameters that Reduce receives:

  arr.reduce(callback[, initialValue])
Copy the code

The reduce method takes a callback function as its first argument, along with an optional initialValue. The callback function also takes up to four arguments

  • The return value of an accumulator callback; It is the cumulative value returned when the callback was last called. If initialValue is provided, its default value is initialValue, otherwise it is the first value of the array
  • CurrentValue Specifies the element currently participating in the calculation
  • CurrentIndex Array index of the current evaluated element
  • Array Array of the current operation

With this in mind, implementing the Reduce approach is straightforward

    Array.prototype.selfReduce = function() {
       const ary = this
       const { length } = ary
       if (arguments.length === 0) {
         throw new TypeError('undefined is not a function')}if (typeof arguments[0]! = ='function') {
         throw new TypeError(arguments[0] + 'is not a function')}if (ary.length === 0 && arguments.length === 1) {
         throw new TypeError('Reduce of empty array with no initial value')}const callback = arguments[0]
       const startIndex = arguments.length >= 2 ? 0 : 1
       let value = startIndex === 0 ? arguments[1] : ary[0]
       for (let i = startIndex; i < length; i++) {
          value = callback(value, ary[i], i, ary)
       }
       return value
    }
Copy the code

At the same time,reduce also has its brother 👬reduceRight, which, as its name suggests, passes each element of an array from right to left into a callback function. That realization reduceRight realization is also simple.

Array.prototype.selfReduceRight = function () {
   const ary = this
   const { length } = ary
   if (arguments.length === 0) {
     throw new TypeError('undefined is not a function')}if (typeof arguments[0]! = ='function') {
     throw new TypeError(arguments[0] + 'is not a function')}if (ary.length === 0 && arguments.length === 1) {
       throw new TypeError('Reduce of empty array with no initial value')}const startIndex = arguments.length >= 2 ? length - 1 : length - 2
   const callback = arguments[0]
   let value = startIndex === 0 ? arguments[1] : ary[length - 1]
   for (let i = startIndex; i >= 0; i--) {
      value = callback(value, ary[i], i, ary)
   }
   return value
}
Copy the code

Write in the last

A little bit of functional programming (FP)

  • Compose (combination)
  • Pipe (pipe)

compose

Compose executes from right to left

Here is the implementation of compose (unhandled exceptions)

const compose = function(. fns) {
    return (val) = > {
        return fns.reduceRight((acc, fn) = > {
            return fn(acc);
        }, val)
    }
};

const add1 = x= > x + 1;
const mult2 = y= > y * 2;

const composeFn = compose(add1, mult2);

composeFn(5); // 11 = 5 * 2 + 1

Copy the code

pipe

Like the inside of the Unix “|”, execution of the pipe from left to right. The following is a very simple command to view the nginx process (written a little bit 😂).

    ps -ef | grep nginx
Copy the code

Here is the implementation of PIPE (unhandled exception case)

const pipe = function(. fns) {
    return (val) = > {
        return fns.reduce((acc, fn) = > {
            return fn(acc);
        }, val)
    }
};

const add1 = x= > x + 1;
const mult2 = y= > y * 2;

const pipeFn = pipe(add1, mult2);

pipeFn(5); // 12 = (5 + 1) * 2
Copy the code

Well, this article is finished, also do not know what to write, in nuggets to write articles not much, so do not know you see the officer’s taste, if the article has written wrong or write bad place, please point out that you see the officer, I also correct 🙏.