[Array method reduce] Details of reduce and simulation rewriting of other array extension methods

Learn key phrases:
Array.reduce
Array.prototype.reduce
reduce method
Override reduce method

1. Write in front

Many students (referring to myself) have no difficulty in learning other array expansion methods, but when it comes to the reduce method, they will appear stupid, so today I will quickly explain this method clearly.

In fact, all array expansion methods essentially use loops and traversals, so they are actually very simple. Today we will not only explain the usage of reduce, but also use reduce to simulate other array expansion methods.

So hurry up and take a look together

2. Start

2.1 How to use reduce

reduce is a method on the array prototype object, so it can be called directly from an array

Let’s first look at the usage form of reduce, as shown in the following code

let initValue = null;
let newArr = arr.reduce(function (pre, cur, index, arr) {<!-- -->
\t// Business code
}, initValue)

We see that there are a total of 4 formal parameters and 1 actual parameter, which are
Formal parameters: pre / cur / index / arr
Actual parameter: initValue

Let’s talk about what these are (in human terms)

  • pre: receive the initValue value of the actual parameter passed in for the first time / receive the value returned by the last function every time except the first time
  • cur: the array element currently being looped to
  • index: the index of the array currently being looped to
  • arr: the array of the current loop
  • initValue: The value of pre manually given for the first time

The first parameter function will be called continuously in the reduce method, so except for the first value of pre which is passed in manually, every subsequent value is the return value of the previous parameter function.

How to determine the value of initValue used for the first time in pre?

let arr = [1];
let initValue = Math.random();
let newArr = arr.reduce(function (pre, cur, index, arr) {<!-- -->
console.log(pre === initValue); // true
}, initValue)

So reduce is not a method used to solve any specific problem, it is a method with a high degree of freedom.

Let’s look at two cases

2.1.1 Case 1: Use of arrays

Requirement: Get the name of the person in data

//Use the reduce method to get the name of the person in each object
let data = [
  {<!-- --> id: 1, name: 'Zhang San', eat: true, age: 24 },
  {<!-- --> id: 2, name: '李思', eat: false, age: 15 },
  {<!-- --> id: 3, name: '王五', eat: false, age: 44 },
  {<!-- --> id: 4, name: 'Zhao Liu', eat: true, age: 22 },
  {<!-- --> id: 5, name: 'Lin Qi', eat: true, age: 24 },
]

let initValue = [];
let nameList = data.reduce(function (pre, cur, index, arr) {<!-- -->
// The first time the value of pre is initValue, an empty object is passed in
// Each time, put the name value of the array element currently looped by cur into pre
// And return pre as the initial value of pre when this function is run next time
    pre.push(cur.name);
    return pre;
}, initValue)
console.log(nameList);

2.1.2 Case 2: Use of objects

Requirement: Take out the browser cookie value and change it into object form

//Get browser cookies
// You can get the cookie here by opening a web page and entering document.cookie from the console.
let cookie = "BIDUPSID=DC121AD5196A1; PSTM=16859; BAIDUID=DC121AD5196A1B69390521:FG=1; BD_UPN=123143; MCITY=-19:; sugstore=0; 521:FG=1; b-user -id=11b5db-7f7c-ca96-7b82-f9338e5; ZFY=gsXyFw:AG:BaAtZlSnw4Z5YZop6iGeZmA:C; RT="z=1 & amp;dm=baidu.com & amp;si=158ae890-f910-4a2e -b2ff-7c56 & amp;ss=lobi6w & amp;sl=2 & amp;tt=1et & amp;bcn=https://fg.baidu.com/log/weirwood?type=perf & amp;ld=ok & amp;ul=4ztx & amp;d=4zvu"; BA_HCTOR=0k2k2g8a5212408501l251l1611q; BDORZ=4905EFF3D40215D2BDA1598; ,16996550,16921029,19997199; COOKIE_SESSION=4682_2_6_9_3_6_1_0_6_9_1_3_38695_24088_0_5_16995956_16994134_16994129|9#247092_108_168441 29|9"
// Split a long string into arrays connected by equal signs
let cookieArr = cookie.split(';')
// Loop through each array
let cookieObj = cookieArr.reduce((pre, item) => {<!-- -->
// Split each item into an array of two elements, namely key name and key value
    let arr = item.split('=');
    // The first time is the empty object passed in, and new attributes are written to the object each time
    pre[arr[0]] = arr[1];
    // Return pre to the next parameter function
    return pre;
}, {<!-- -->})
console.log(cookieObj);

In fact, the case doesn’t explain much. As I said above, the reduce method is too free and can basically implement anything. However, there is another problem, that is, the reduce method was proposed by ES5 and there is no way to make it compatible with lower versions. We can only override our own reduce method

2.2 Rewrite the reduce method

If you want to override an array method, you must first look at how to use this method. We have already learned about it above.

So we know that our reduce method needs to receive two parameters, one is the callback function and the other is the initial value

Array.prototype.myReduce = function (fn, initValue) {<!-- -->
  var arr = this;
  for (var i = 0; i < arr.length; i + + ) {<!-- -->
  //The first time the passed in fn method is executed, the value of pre is passed in directly from initValue
  //After each execution of the fn method, assign the return value to initValue and proceed to the next cycle
  // Each time a new loop executes the fn method, the initValue value returned by the previous loop will be used
  // That is, the value of each pre is the value returned by the previous loop
    initValue = fn(initValue, arr[i], i, arr);
  }
  return initValue;
}

But we know that other array extension methods can specify what this in the function points to, so we modify it slightly

Array.prototype.myReduce = function (fn, initValue) {<!-- -->
  var arr = this,
  // If the user does not pass in the specified this point, then point to window
    arg2 = arguments[2] || window;
  for (var i = 0; i < arr.length; i + + ) {<!-- -->
  // Use call to change the this pointer of the fn function, and leave everything else unchanged
    initValue = fn.call(arg2, initValue, arr[i], i, arr);
  }
  return initValue;
}

2.3 reduce simulates other array methods

The reduce method is a method with a high degree of freedom. You can even use it to complete other array expansion methods. Let’s try it now.

2.3.1 reduce simulates forEach method

forEach is one of the most common extension methods. It is too useless to simulate it with reduce. The role of reduce is to loop the array.

Array.prototype.myForEach = function (fn) {<!-- -->
  var arr = this,
    arg2 = arguments[1] || window;
  arr.reduce(function (pre, cur, index, arr) {<!-- -->
  //The parameters required in forEach are elements, indexes, and arrays. Just write them one by one.
    fn.call(arg2, cur, index, arr);
    // Loop traversal does not require return
  }, null)
}

2.3.2 reduce simulates filter method

The role of reduce in filter is to loop through the array

Array.prototype.myFilter = function (fn) {<!-- -->
  var arr = this,
    arg2 = arguments[1] || window,
    res = [];
  arr.reduce(function (pre, cur, index, arr) {<!-- -->
  // When the return value of the parameter function is true, this element needs to be put into the return array
    fn.call(arg2, cur, index, arr) ? res.push(cur) : ''
  }, null)
  return res;
}

2.3.3 reduce simulates map method

The role of reduce in map is to loop through the array

Array.prototype.myMap = function (fn) {<!-- -->
  var arr = this,
    arg2 = arguments[1] || window,
    res = [];
  arr.reduce(function (pre, cur, index, arr) {<!-- -->
  // Directly put the return value of the parameter function into the return array
    res.push(fn.call(arg2, cur, index, arr))
  }, null)
  return res;
}

2.3.4 reduce simulates every and some methods

The role of reduce in every is to loop through the array

Array.prototype.myEvery = function (fn) {<!-- -->
  var arr = this,
    arg2 = arguments[1] || window,
    res = true;
  arr.reduce(function (pre, cur, index, arr) {<!-- -->
  // As long as the parameter function returns false once, return false
    if (!fn.call(arg2, cur, index, arr)) {<!-- -->
      res = false;
    }
  }, null)
  return res;
}

The role of reduce in some is to loop through the array

Array.prototype.mySome = function (fn) {<!-- -->
  var arr = this,
    arg2 = arguments[1] || window,
    res = false;
  arr.reduce(function (pre, cur, index, arr) {<!-- -->
  //As long as the parameter function returns true once, return true
    if (fn.call(arg2, cur, index, arr)) {<!-- -->
      res = true;
    }
  }, null)
  return res;
}

3. Summary

As an array extension method introduced in ES5, reduce is also one of the things that the front-end must learn. At the same time, in the process of rewriting and simulating other methods, we can clearly understand that the extension method is essentially a loop traversal and then calling the incoming Just a function of

4. End

The explanation of reduce has come to an end. I hope you have really learned something. If you use a for loop to replace the reduce method in the simulation part, it is a rewrite of other array methods.

If you encounter any problems that cannot be achieved while following this, please tell me in the comment area or private message , and I will mobilize netizens to answer your questions