preface

Array types in JavaScript provide many native methods to use, and this article will simulate the implementation of some common array apis.

In addition, I am also constantly learning, if there is something wrong, please correct it, I will update in time, thank you.

Blog address๐Ÿน ๐Ÿฐ fe – code

API

There are a lot of apis for arrays, so I’m going to put some of the more common ones here. If you have other ways to do this, you can put them in the comments section and I will update them in the article.

This article is not intended to cover the basic uses of any particular API, so those unfamiliar with these API uses need to learn them on their own. Most of the other implementations are on MDN.Copy the code

Go to — > MDN to learn the basics.

Before we start the implementation in earnest, let’s take a look at an example.

let arr = [];
arr[3] = 3;
// arr.length ? arr[0] ? 0 in arr ?

// 4 undefined fasle
Copy the code

This is something that’s going to come up later in the implementation, so let’s look at it. Array subscripts are not necessarily contiguous, and direct assignment can also affect its length.

forEach

  • Simple implementation
// forEach supports passing in two arguments, callback and thisArg
// Callback returns three parameters: the current element, the current element index, and the original array
If thisArg is passed, change the this pointer to the callback
Array.prototype.myforeach = function (fn, context = null) {
    let index = 0;
    let arr = this;
    if (typeoffn ! = ='function') {
        throw new TypeError(fn + ' is not a function');
    }
    while (index < arr.length) {
        if (index in arr) { // Array subscripts are not necessarily contiguousfn.call(context, arr[index], index, arr); } index ++; }};Copy the code
  • Support the async/await

I’ve seen the bigwigs discuss this before, so I bring it up. ForEach will not be able to synchronize in the normal case. The program will not wait for the asynchrony in one loop to complete before proceeding to the next. For obvious reasons, in the above simulation, the while loop simply executes the callback, so even if we use await inside the callback, it only affects the inside of the callback.

arr.myforeach(async v => {
    await fetch(v);
});
Copy the code

To support this notation, you just have to change it a little bit.

Array.prototype.myforeach = async function (fn, context = null) {
    let index = 0;
    let arr = this;
    if (typeoffn ! = ='function') {
        throw new TypeError(fn + ' is not a function');
    }
    while (index < arr.length) {
        if (index in arr) {
            try {
                await fn.call(context, arr[index], index, arr);
            } catch (e) {
                console.log(e); } } index ++; }};Copy the code

map

Map is implemented in much the same way as forEach, except that it returns a new array.

// The arguments are the same as forEach
// Callback needs a return value
Array.prototype.mymap = function (fn, context = null) {
    let arr = this;
    let len = arr.length;
    let index = 0;
    let newArr = [];
    if (typeoffn ! = ='function') {
        throw new TypeError(fn + ' is not a function');
    }
    while (index < len) {
        if (index in arr) {
            let result = fn.call(context, arr[index], index, arr);
            newArr[index] = result; // Return the value as a new array
        }
        index ++;
    }
    return newArr;
};
Copy the code

reduce

Reduce is slightly more cumbersome and requires a different processing depending on whether the second parameter exists.

Array.prototype.myreduce = function (. arg) {
    let arr = this;
    let len = arr.length;
    let index = 0;
    let fn = arg[0], result;
    if (arg.length >= 2) { // Check if there is a second argument, if so, as the initial value to run the callback function
        result = arg[1];
    } else {
        // Reduce, in the absence of a second argument, takes the first item of the array as the initial value of the callback
        // The first term is not necessarily a[0]
        while(index < len && ! (indexin arr)) {
        // If the subscript is less than the length of the array and does not belong to the array, keep looping to find the first item in the array
            index++;
        }
        if (index >= len) { // If the first item is greater than or equal to the length of the array, it is an empty array
            throw new TypeError( 'Empty array with no initial value' );
        }
        result = arr[index++]; // assign the subscript +1
    }
    if (typeoffn ! = ='function') {
        throw new TypeError(fn + ' is not a function');
    }
    while (index < len) {
        if (index in arr) {
            result = fn(result, arr[index], index, arr); // The return value of each callback is passed to the next callback
        }
        index ++;
    }
    return result;
};
Copy the code

Reduce implements a map

This question is often asked in an interview. Write it down.

Array.prototype.mapByreduce = function (fn, context = null) {
    let arr = this;
    if (typeoffn ! = ='function') {
         throw new TypeError(fn + ' is not a function');
    }
    return arr.reduce((pre, cur, index, array) = > {
        let res = fn.call(context, cur, index, array);
        return [...pre, res]; Return a new array} []); };Copy the code

filter

Filter is generally used for filtering.

Array.prototype.myfilter = function (fn, context = null) {
    let arr = this;
    let len = arr.length;
    let index = 0, k = 0;
    let newArr = [];
    if (typeoffn ! = ='function') {
        throw new TypeError(fn + ' is not a function');
    }
    while (index < len) {
        if (index in arr) {
            let result = fn.call(context, arr[index], index, arr);
            if (result) newArr[k++] = arr[index]; // If the return value is true, add to the new array
        }
        index ++;
    }
    return newArr;
};
Copy the code

Find and findIndex

Find is similar to filter in that it returns the current element if it finds one, and undefined if it does not.

FindIndex returns -1 if not found. Similar to indexOf, except that callbacks are supported.

Array.prototype.myfind = function (fn, context = null) {
    let arr = this;
    let len = arr.length;
    let index = 0;
    if (typeoffn ! = ='function') {
        throw new TypeError(fn + ' is not a function');
    }
    while (index < len) {
        if (index in arr) {
            let result = fn.call(context, arr[index], index, arr);
            if (result) return arr[index]; // Return if the condition is satisfied
        }
        index ++;
    }
    return undefined;
};
Copy the code

some

Some and find are the same, except that they return a different value.

Array.prototype.mysome = function (fn, context = null) {
    let arr = this;
    let len = arr.length;
    let index = 0;
    if (typeoffn ! = ='function') {
        throw new TypeError(fn + ' is not a function');
    }
    while (index < len) {
        if (index in arr) {
            let result = fn.call(context, arr[index], index, arr);
            if (result) return true; // If one is found, return true immediately
        }
        index ++;
    }
    return false; // Return false if not found
};
Copy the code

every

As opposed to some, this returns true if each member meets the criteria and false if one member does not.

Array.prototype.myevery = function (fn, context = null) {
    let arr = this;
    let len = arr.length;
    let index = 0;
    if (typeoffn ! = ='function') {
        throw new TypeError(fn + ' is not a function');
    }
    while (index < len) {
        if (index in arr) {
            let result = fn.call(context, arr[index], index, arr);
            if(! result)return false; // If one is not satisfied, return false
        }
        index ++;
    }
    return true;
};
Copy the code

Filter, find, some, and every are all similar in implementation and function, but there are some differences in return value, so it is more important to use the appropriate method in the appropriate scenario.

Includes and indexOf

Either of these can be used to find out if there is an element in the array, but the return value is different.

Array.prototype.myincludes = function (val, fromIndex = 0) {
    let arr = this;
    let len = arr.length;
    let k = Math.max(fromIndex >= 0 ? fromIndex : len - Math.abs(fromIndex), 0);
    // Allow negative numbers to be passed in, which means starting from the last digit
    // Negative numbers are still looked up in ascending order
    // Avoid passing a negative value greater than len so that k appears negative. Set k to the minimum value 0
    function check(x, y) {
        return x === y ||
        (typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y));
        / / determine NaN
    }
    while (k < len) {
        if (k in arr) {
            if (check(val, arr[k])) return true; // Find a match, return true
        }
        k ++;
    }
    return false; // Return false if not found
};
Copy the code
// indexOf does not support finding nans
Array.prototype.myindexOf = function (val, fromIndex = 0) {
    let arr = this;
    let len = arr.length;
    let k = Math.max(fromIndex >= 0 ? fromIndex : len - Math.abs(fromIndex), 0);
    // handle negative numbers
    while (k < len) {
        if (k in arr) {
            if (val === arr[k]) return k; // find the return subscript
        }
        k ++;
    }
    return -1; // Return -1 if not found
};
Copy the code

join

Convert an array to a string using a concatenator

Array.prototype.myjoin = function (connector = ', ') {
    let arr = this;
    let len = arr.length;
    let str = ' ';
    let k = 0;
    while (k < len) {
        if (k in arr) {
            if (k === len -1) { // The last bit is not connected
                str += arr[k];
            } else {
                str += arr[k] + connector.toString();
            }
        }
        k ++;
    }
    return str;
};
Copy the code

Okay, that’s about it, and let me know if you feel you need to add anything.

Refer to the article

  • MDN

Communication group

Qq front-end communication group: 960807765, welcome all kinds of technical exchanges, looking forward to your joining;

Wechat group: If you need it, you can add me as a friend and I will pull you into the group. There is a QR code at the end of the article.

Afterword.

If you see here, and this article is a little help to you, I hope you can move a small hand to support the author, thank ๐Ÿป. If there is something wrong in the article, we are welcome to point out and encourage each other. Thanks for reading. See you next time!

  • The article warehouse ๐Ÿน ๐Ÿฐ fe – code
  • Social chat system (vue + Node + mongodb) – ๐Ÿ’˜๐Ÿฆ๐Ÿ™ˆVchat

Recent Articles:

  • ใ€ from head to toe ใ€‘ Front-end implementation of multi-person video chat — WebRTC combat (multiplayer)
  • ใ€ ใ€‘ from head to foot WebRTC + Canvas to achieve a double collaborative Shared sketchpad essay | the nuggets technology
  • [2019 Front-end advanced road] In-depth Vue responsive principle, from the source analysis
  • Vue component communication mode complete version

Interested students can pay attention to my public number front-end engine, fun and material. Also can add my friend, we learn to exchange ^_^.