Reduce its sharp, solve its dispute, and its light, with its dust.

Introduction to the

Array.prototype has a lot of methods, can be very convenient to implement a variety of loop, filter Array to do a lot of processing, here mainly record myself how to implement several methods map, forEach, filter, reduce, I’m not going to talk much about how to use it because there’s a lot of discussion about Array in MDN and other people’s articles.

To realize the reduce

Reduce takes two arguments. The first argument is a callback method and the second argument is an initialValue, initialValue. The general implementation steps are as follows:

  • Determines whether the calling method itself is Array
  • Declare the variables to use
  • Check if there is an initial value. If there is no initial value, fetch it from its own array and jump out of the loop
  • Loop through callback
Array.prototype.selfReduce = function(callback, initalValue) {
  // Cannot be null calling method
  if (this= = =null) {
    throw new TypeError(
      "Array.prototype.reduce" + "called on null or undefined"
    );
  }
  // The first argument must be function
  if (typeofcallback ! = ="function") {
    throw new TypeError(callback + " is not a function");
  }
  // Declare the variables to use
  // The array to loop through
  let arr = Array.prototype.slice.call(this);
  let _len = arr.length;
  // Result array
  let res = [];
  // The initial array index defaults to 0
  let startIndex = 0;

  // Check whether there is an initial value initalValue
  if (initalValue === undefined) {
    // If the initial value is undefined, the loop finds a value in the array and exits the loop
    // Filter the sparse values
    for (let i = 0; i < _len; i++) {
      if(! arr.hasOwnProperty(i)) {continue;
      } else {
        startIndex = i;
        res = arr[i];
        break; }}}else {
    res = initalValue;
  }

  // Get the initial value in the previous step, loop through the incoming callback function, and filter the loose values
  for (let i = startIndex++; i < arr.length; i++) {
    if(! arr.hasOwnProperty(i)) {continue;
    }
    res = callback.call(null, res, arr[i], i, this);
  }
  return res;
};
Copy the code

Test selfReduce and Reduce methods to see if they behave the same:

var aTest = [1.2.3.4.5];
arr.reduce((prev, next) = > {
  return prev + next;
}, 0); / / 15
arr.selfReduce((prev, next) = > {
  return prev + next;
}, 0); / / 15
Copy the code

You can also check out the official MDN Reduce Polyfill.

To realize the map

Map is implemented in two ways, one through the for loop and the other through reduce.

For loop implementation

Array.prototype.selfMap = function(callback, context) {
  // Cannot be null calling method
  if (this= = =null) {
    throw new TypeError(
      "Array.prototype.reduce" + "called on null or undefined"
    );
  }
  // The first argument must be function
  if (typeofcallback ! = ="function") {
    throw new TypeError(callback + " is not a function");
  }
  // Declare the variables to use
  let arr = Array.prototype.slice.call(this);
  let _len = arr.length;
  let aMap = [];
  // loop call
  for (let i = 0; i < _len; i++) {
    // Filter the sparse values
    if(! arr.hasOwnProperty(i)) {continue;
    }
    aMap[i] = callback.call(context, arr[i], i, this);
  }
  return aMap;
};
Copy the code

To test whether selfMap and Map are consistent, the code is as follows:

var aTest = [1.2.3.4.5];
aTest.map(item= > {
  return item * 2;
}); // [2, 4, 6, 8, 10]
aTest.selfMap(item= > {
  return item * 2;
}); // [2, 4, 6, 8, 10]
Copy the code

Reduce implementation

Array.prototype.reduceMap = function(callback, context) {
  // Cannot be null calling method
  if (this= = =null) {
    throw new TypeError(
      "Array.prototype.reduce" + "called on null or undefined"
    );
  }
  // The first argument must be function
  if (typeofcallback ! = ="function") {
    throw new TypeError(callback + " is not a function");
  }
  // Get the array
  let aMap = Array.prototype.slice.call(this);
  // Use reduce to implement loops
  return aMap.reduce((pre, cur, index) = > {
    // Concatenate the result of the last loop with the current result
    // loop through callback
    return [...pre, callback.call(context, cur, index, this)]; } []); };Copy the code

To test whether the implementation of reduceMap and MAP are consistent, the code is as follows:

var aTest = [1.2.3.4.5];
aTest.map(item= > {
  return item * 2;
}); // [2, 4, 6, 8, 10]
aTest.reduceMap(item= > {
  return item * 2;
}); // [2, 4, 6, 8, 10]
Copy the code

The filter implementation

Filter is also used many times, so I won’t go into details here. Let’s look at two implementations:

For loop implementation

Array.prototype.selfFilter = function(callback, context) {
  // Cannot be null calling method
  if (this= = =null) {
    throw new TypeError(
      "Array.prototype.reduce" + "called on null or undefined"
    );
  }
  // The first argument must be function
  if (typeofcallback ! = ="function") {
    throw new TypeError(callback + " is not a function");
  }
  // Get the array
  let aArr = Array.prototype.slice.call(this);
  let _len = aArr.length;
  let aFArr = [];
  // loop through callback
  for (let i = 0; i < _len; i++) {
    if(! aArr.hasOwnProperty(i)) {continue;
    }
    callback.call(context, aArr[i], i, this) && aFArr.push(aArr[i]);
  }
  return aFArr;
};
Copy the code

Reduce implementation

Array.prototype.reduceFilter = function(callback, context) {
  // Cannot be null calling method
  if (this= = =null) {
    throw new TypeError(
      "Array.prototype.reduce" + "called on null or undefined"
    );
  }
  // The first argument must be function
  if (typeofcallback ! = ="function") {
    throw new TypeError(callback + " is not a function");
  }
  // Get the array
  let aArr = Array.prototype.slice.call(this);

  // loop through callback
  aArr.reduce((pre, cur, index) = > {
    return callback.call(context, cur, index, this)? [...pre, cur] : [...pre]; } []);return aArr;
};
Copy the code

The test code

var aTest = [1.2.3.4.5.6];
aTest.filter(item= > {
  return item > 2;
});
aTest.selfFilter(item= > {
  return item > 2;
});
aTest.reduceFilter(item= > {
  return item > 2;
});
Copy the code

To realize the forEach

For loop implementation

Array.prototype.selfForeach = function(callback, context) {
  // Cannot be null calling method
  if (this= = =null) {
    throw new TypeError(
      "Array.prototype.reduce" + "called on null or undefined"
    );
  }
  // The first argument must be function
  if (typeofcallback ! = ="function") {
    throw new TypeError(callback + " is not a function");
  }
  // Get the array
  let arr = Array.prototype.slice.call(this);
  let _len = arr.length;
  for (let i = 0; i < _len; i++) {
    callback.call(context, arr[i], i, arr);
  }
  return arr;
};
Copy the code

Reduce cycle implementation

Array.prototype.reduceForeach = function(callback, context) {
  // Cannot be null calling method
  if (this= = =null) {
    throw new TypeError(
      "Array.prototype.reduce" + "called on null or undefined"
    );
  }
  // The first argument must be function
  if (typeofcallback ! = ="function") {
    throw new TypeError(callback + " is not a function");
  }
  // Get the array
  let arr = Array.prototype.slice.call(this);
  arr.reduce((pre, cur, index) = > {
    return [...pre, callback.call(context, cur, index, this)]; } []); };Copy the code

conclusion

Basically understand how to implement, whether using for or reduce implementation, basically there is no big difference. Writing is not easy, if you like likes, attention

reference

Array.prototype.reduce()

28 JavaScript Skills a qualified intermediate front-end engineer needs to master

JS array. reduce implements array. map and array. filter