This is the seventh day of my participation in the August More text Challenge. For details, see: August More Text Challenge

This article will first understand the use of the array API and then simulate the implementation of these APIS, if you feel there is something wrong with the trouble to point out the following!

1. The forEach method

This method runs the passed function on each element of the array, returning no value. This is equivalent to using a for loop to traverse the array. Such as:

let numbers = [1.2.3.4.5.4.3.2.1];
numbers.forEach((item, index, array) = > {
    // Perform some operations
    item += 2
})
console.log(numbers);
Copy the code

We find that it doesn’t change the elements of the array

Instead of a for loop, you can use the forEach method to iterate through the array

Let’s take a look at the code below and summarize

let arr1 = [{
    name: 'ljc'.age: 19
}, {
    name: 'xy'.age: 18
}]
arr1.forEach(item= > {
    item.age += 1
})
console.log(arr1);
Copy the code

From the above code, we can see that the age attribute value of both members is increased by 1

So we can simply conclude that forEach will never change an array if its elements are of value type. You can change an array when its elements are of reference type

Note: forEach does not support chained operations because the forEach method does not return a value

1-1 Handwritten forEach methods

The native forEach method takes two arguments, callback and thisArg, and the callback function is passed three arguments, the value of the current item in the array, the index, and the array itself

Array.prototype.myForEach = function (callback, thisArg) {
    // Check whether the element calling the API is null
    if (this= =null) {
        throw new TypeError('this is null or not defined')}// Check whether it is function
    if (typeofcallback ! = ="function") {
        throw new TypeError(callback + ' is not a function')}// Get the caller arr from this
    const arr = this
    // Determine the loop variable
    let index = 0
    // Call callback for each array element through the loop
    while (index < arr.length) {
        // Check whether this item exists
        if (index in arr) {
            // Call this to thisArg, passing three arguments
            callback.call(thisArg, arr[index], index, arr)
        }
        index++
    }
}
Copy the code

2. The map method

Compared to the forEach method, the map method returns a value and the forEach method does not return a value.

A map is also called a mapping, which is to map the original array to a new array

  1. Each element in the array calls one of the provided functions and returns the result.
  2. It’s going to create an array, it’s going to have a host object, so it’s going to return a new object
  3. The original array does not change unless it is hosted by the original array

Method of use

let arr = [1.2.3.4.5]
let newArr = arr.map(item= > item * 2)
console.log(newArr); // [2, 4, 6, 8, 10]
Copy the code

Map needs to have a return value, which can be abbreviated using the arrow function

Easy wrong points

Each element in the map executes a callback function, so a return is required, so you cannot filter an array using a map

You can see the gray undefined. Bye

2-2 Handwritten map method

  1. First rule out empty arrays and no callback functions
  2. According to themapCreate an array, execute a function, and return the array
Array.prototype.myMap = function (callback, thisArg) {
    // The same as forEach requires two exclusions
    if (this= =undefined) {
        throw new TypeError('this is null or not defined');
    }
    if (typeofcallback ! = ='function') {
        throw new TypeError(callback + ' is not a function');
    }
    // Unlike forEach, map returns a new array
    const ret = []
    // Get the function caller
    const arr = this
    // Array length
    let len = arr.length
    // Perform a callback function for each element
    for (let i = 0; i < len; i++) {
        // Check if I is in the ARR
        if(i in arr) {
            ret[i] = callback.call(thisArg, arr[i], i, arr)
        }
    }
    // Return a processed array
    return ret
}
Copy the code

3. filter

The name filter is used to filter information. As with map, a new array of objects is returned, without changing the original array

Method of use

Thus, the element of the filter array elements less than 3 elements

3-3 Handwritten filter method

Compared to the MAP method, filter needs to return the elements that satisfy the condition as a new array

Array.prototype.myFilter = function(callback,thisArg) {
    if (this= =undefined) {
        throw new TypeError('this is null or not defined');
    }
    if (typeofcallback ! = ='function') {
        throw new TypeError(callback + ' is not a function');
    }
    / / the new array
    const res = []
    / / save this
    const arr = this
    // Calculate the array length in advance
    const len = arr.length
    for(let i = 0; i<len; i++) {if(i in arr) {
            // Check whether the element returns a value after the function call
            // To determine whether the filter rules are met,
            if(callback.call(thisArg,arr[i],i,arr)) {
                res.push(arr[i])
            }
        }
    }
    // Return a new array
    return res
}
Copy the code

4. Some methods

The some method checks whether there are any values in the array that match the criteria. The return value is a Boolean value

Method of use

Some methods are performance friendly because they don’t need to go through all of them, but return true if they find one that fits the criteria

We can write a some method according to this principle

4-4 Write some methods

Array.prototype.mySome = function (callback, thisArg) {
    if (this= =undefined) {
        throw new TypeError('this is null or not defined');
    }
    if (typeofcallback ! = ='function') {
        throw new TypeError(callback + ' is not a function');
    }
    let arr = this
    let len = arr.length
    for (let i = 0; i < len; i++) {
        if (i in arr) {
            if (callback.call(thisArg, arr[i], i, arr)) {
                return true}}}return false
}
Copy the code

5. Every method

Return true if each member satisfies the condition, and false if one member does not

True will only be returned if all satisfies

5-5 Write every

Array.prototype.myEvery = function (callback, thisArg) {
    if (this= =undefined) {
        throw new TypeError('this is null or not defined');
    }
    if (typeofcallback ! = ='function') {
        throw new TypeError(callback + ' is not a function');
    }
    const arr = this
    const len = arr.length
    for (let i = 0; i < len; i++) {
        if (i in arr) {
            if(! callback.call(thisArg, arr[i], i, arr)) {return false}}}return true
}
Copy the code

6. Find and findIndex methods

If an element is found, return the current element. If not, return undefined

Similar to find is the findIndex method, which returns the index of the first element that satisfies the condition

How to use find

Returns the satisfying elements

FindIndex Usage method

Returns the index that satisfies

6-6 Handwritten find method

Loop through the array, call the function, and return the first element of the array if the condition is met

Array.prototype.myFind = function (callback, thisArg) {
    if (this= =undefined) {
        throw new TypeError('this is null or not defined');
    }
    if (typeofcallback ! = ='function') {
        throw new TypeError(callback + ' is not a function');
    }
    // Save this, the caller
    const arr = this
    const len = arr.length
    for (let i = 0; i < len; i++) {
        if (i in arr) {
            if (callback.call(thisArg, arr[i], i, arr)) {
                return arr[i]
            }
        }
    }
    return undefined
}
Copy the code

FindIndex method

Return arr[I] : return arr[I] : return I

Small scene

If you look at the six or seven array methods above, you’ll notice that the difference in implementation is just a few lines of code, and it’s not easy to remember, but what are the usage scenarios, and how do I get in there, and use a little scenario to show how these APIS are used

Previously: In a company, the boss is considering to give employees a promotion and a raise…

Company employee Data

let staff = [
    {name: 'a'.salary: 20000.age: 36},
    {name: 'b'.salary: 19000.age: 34},
    {name: 'c'.salary: 18000.age: 20},
    {name: 'd'.salary: 17000.age: 18}]Copy the code

🤵 boss: “This year’s performance is good, the salary of all employees increased 1000”

👨🦲 programmer: “Simple, use forEach, the code and results look like this”

staff.forEach(item= > item.salary += 1000)
Copy the code

🤵 boss: “Put together a salary form for me”

👨🦲

w = staff.map(item= > item.salary += 1000)
console.log(w) // [21000, 20000, 19000, 18000]
Copy the code

🤵 boss: “the company has been established for so many years, give me a list of our company’s employees who are over 33 years old.”

👨🦲 Programmer: “Ok, no problem, use filter”

w = staff.filter(item= > item.age > 33)
Copy the code

👨🦲 Programmer: “Employee A and EMPLOYEE B are all over 33 years old”

🤵 boss: “that you again help me to see have the employee under 18 years old”

👨🦲 Programmer: “Ok, I used some methods to look, we have no employees under the age of 18”

w = staff.some(item= > item.age < 18) // false
Copy the code

🤵 boss: “the company is listed now, you see our company employee salary is 1.6 W above”

👨🦲 programmer small elder brother: “really good, all 1.6 W above, still have what need?”

w = staff.every(item= > item.salary > 16000) // true
Copy the code

🤵 boss: “that you again help me find an age 35 years old above of, the first good”

👨🦲 programmer small elder brother: “simple checked the first more than 35, call a”

w = staff.find(item= > item.age > 35) // {name: "a", salary: 20000, age: 36}
Copy the code

🤵 boss: “it in the company’s employee data row in a few ah”

👨🦲 programmer small brother: “you are boring, this all want to see”

w = staff.findIndex(item= > item.age > 35) / / 0
Copy the code

👨🦲 Programmer: “0, first, veteran level”

🤵 boss: “pretty good, your technology is not bad, that you calculate salary sum, call secretary dozen money to finance”

👨🦲 Programmer: “…. Wait, LET me learn reduce again.”

7. The reduce method

Unlike the iterative method, reduce is a merging method. The merging method does not execute the objective function for each item. It can be summarized as the following steps:

  1. You take the first two items of the array, execute the target function on it, and calculate the return value
  2. Insert the return value at the beginning of the array, that is, asayyay[0]
  3. This process continues until each item in the array is accessed once
  4. Return the final result

For example

const arr = [1.2.3]
const res = arr.reduce((prev, cur) = > prev + cur)
console.log(res); / / 6
Copy the code

In the above code, Reduce takes a few steps to merge

[1, 2, 3] // Take out 1 and 2, execute 1 + 2 to fill back 3 [3, 3] // Take out 3 3, fill back 6 [6] // Finally return 6Copy the code

7-7 Handwriting reduce method

Write according to the 4 step rule above

Array.prototype.myReduce = function (callback, initialValue) {
    // Check whether the element calling the API is null
    if (this= =null) {
        throw new TypeError('this is null or not defined')}// Check whether it is function
    if (typeofcallback ! = ="function") {
        throw new TypeError(callback + ' is not a function')}const arr = this
    const len = arr.length
    // The second argument
    let accumulator = initialValue
    let index = 0
    // If the second argument is undefined, the first value of the array is valid
    // As the initial value of the accumulator
    if (accumulator === undefined) {
        // Find the first valid value in the array is not necessarily arr[0]
        while(index < len && ! (indexin arr)) {
            index++
        }
        if (index >= len) {
            throw new TypeError('Reduce of empty array with no initial value')}// Prints the first valid array element as the first element of the accumulator
        accumulator = arr[index++]
    }
    while (index < len) {
        if (index in arr) {
            // arr[index] is the next element in the accumulator
            accumulator = callback.call(undefined, accumulator, arr[index], index, arr)
        }
        // Keep moving backward
        index++
    }
    // Return the result
    return accumulator
}
Copy the code

7-x Uses Reduce to implement map

You see this topic in a lot of places

Implementation idea: every time the element traversal, as the parameter of the passed function, and the result of the function execution into a new array returned

Core: The map function takes a function as an argument, and the function as an argument takes three parameter values: each element in the traversal array, the index of the element, and the array itself. These three arguments correspond exactly to the second, third, and fourth arguments of the first function argument received by the Reduce function

Array.prototype.mapReduce = function (callback, context = null) {
    if (this= =null) {
        throw new TypeError('this is null or not defined')}// Check whether it is function
    if (typeofcallback ! = ="function") {
        throw new TypeError(callback + ' is not a function')}let arr = this
    return arr.reduce((pre, cur, index, array) = > {
        let res = callback.call(context, cur, index, array)
        return [...pre, res]
    })
}
Copy the code

Thank you very much for your reading and your comments are welcome. Any questions are welcome to point out. Thank you! 🎈