手动实现-01-js的数组的原生方法

94 阅读2分钟

数组方法手写实现

map 和 filter的区别 find 和 findIndex的区别 filter 和 find的区别 forEach 和 单独的for循环区别 some 和 every的区别

自己写的类型检测

// 自己写的类型检测方法
class TypeCheck {
    static common (vm) {
        return Object.prototype.toString.call(vm).match(/^\[object\s(.*)\]$/)[1];
    }

    static isArray (that) {
        return TypeCheck.common(that) === 'Array';
    }

    static isObject (that) {
        return TypeCheck.common(that) === 'Object'; 
    }

    static isUndefined (that) {
        return TypeCheck.common(that) === 'Undefined';
    }

    static isEmptyObject (that) {
        let isObj = TypeCheck.isObject(that);
        let isNull = false
        if (isObj) {
            isNull = Object.keys(that).length == 0;
        }
        return isObj && isNull;
    }

    static isNumber (that) {
        let isNumber = TypeCheck.common(that) === 'Number';
        let isNaN = TypeCheck.isNaN(that);
        return isNumber && !isNaN;
    }

    static isNaN (that) {
        return Number.isNaN(that);
    }
}

forEach

/**
 * 数组的forEach方法实现
 * 功能遍历数组  且第二个参数 在不是箭头函数的情况下 可以改变this指向
 */
let obj = {
    add: (x) => {
        return x + 1
    }
}


function myForEach(callback, thisArg) {
    // 是否是一个方法
    if (typeof callback != 'function') {
        throw Error('不是一个方法')
    }
    let arr = this;
    let that = thisArg;

    if (that) {
        for (const [index, value] of arr.entries()) {
            callback.call(that, value, index, arr);
        }
    } else {
        for (const [index, value] of arr.entries()) {
            callback(value, index, arr);
        }
    }
}

Array.prototype.myForEach = myForEach;

// 这个thisArg 值对箭头函数无效
arr1.myForEach(function(item){
    console.log(item)
    console.log(this.add(item))
    console.log('*********分割符号**********')
}, obj)

Snipaste_2023-03-28_18-04-53.png

map

/*
数组的map 方法
功能:返回满足条件的新数组  
*/

function myMap (callback) {
    // 判断是否是函数
    if (Object.prototype.toString.call(callback).match(/\[object\s(.*)\]$/)[1] !== 'Function') {
        throw Error('不是一个函数');
    }

    let temp = [];
    let arr = this;
    for(let i = 0; i < arr.length; i++) {
        temp.push(callback(arr[i], i, arr))
    }

    return temp;
}
Array.prototype.myMap = myMap;
let arr1 = [1, 2, 3, 4, 5, 6, 7]
let result = arr1.myMap((item) => {if(item==5){return item}})
console.log('result', result);
//[undefined, undefined, undefined, undefined, 5, undefined, undefined]

Snipaste_2023-03-28_19-43-56.png

find

/*
数组的find 方法
功能: 查找符合条件的项,找不到返回undefined
*/

//callback 方法 () => {}
function myFind(callback) {
    // callback 是否是函数
    if (Object().toString.call(callback) != '[object Function]') {
        return '这不是一个函数';
    }

    // 定义虚拟arr
    let arr = this;

    // 寻找的值
    let findItem;
    let arrLength = arr.length;
    for (let i = 0; i < arrLength; i++) {
        if (callback(arr[i], i, arr)) {
            findItem = arr[i];
            break;
        }
    }

    return findItem;
}

Array.prototype.myFind = myFind;

let arr1 = [1, 2, 3]

let result1 = arr1.myFind((item, index, arr) => {return item === 4})   // undefined
let result2 = arr1.myFind((item, index, arr) => {return item ===1})   // 1

Snipaste_2023-03-28_19-49-47.png

findIndex

/**
 * findIndex
 * 功能 找到符合条件的返回索引值 否则返回-1
 * 
 */

function myFindIndex(callback) {
    if(typeof callback != 'function') {
        throw Error('此函数不是一个方法');
    }

    const arr = this;
    let findIndex = -1;

    for(const [index, value] of arr.entries()) {
        if(callback(value, index, arr)) {
            findIndex = index;
            break
        }
    }

    return findIndex;
}

Array.prototype.myFindIndex = myFindIndex;

const arr = [{name: '孙悟空'}, {name: '猪八戒'}, {name: '唐僧'}]

let result1 = arr.myFindIndex(item => item.name == '沙悟净') //-1
let result2 = arr.myFindIndex(item => item.name == '猪八戒')  // 1
console.log('结果一', result1, '\n结果二', result2)

Snipaste_2023-03-28_17-58-10.png

filter

/**
 * filter 方法
 * 功能 返回新的数组 满足条件的数据
 */

function myFilter (callback) {
   if (Object.prototype.toString.call(callback) !== '[object Function]') {
       throw Error('不是一个方法')
   }

   let arr = this;
   let filterArr = [];
   for (const [index, value] of arr.entries()) {
       callback(value, index, arr) ? filterArr.push(value) : '';
   }

   return filterArr;
}

Array.prototype.myFilter = myFilter;
let arrName = new Array({name: '张三'}, {name: '李四'}, {name: '王五'});
let target = arrName.myFilter((item) => item.name == '李四');
console.log(target)

Snipaste_2023-03-28_19-56-44.png

some

/**
 * some 方法
 * 功能 当找到满足的值 结束遍历 返回boolean值
 */
let arrName = new Array({name: '张三'}, {name: '李四'}, {name: '王五'},{name: '赵六'});
function mySome (callback) {
    if (typeof callback != 'function') {
        throw Error('不是一个方法')
    }

    let arr = this;
    let isHave = false

    for(const [index, value] of arr.entries()) {
        if (callback(value, index, arr)) {
            isHave = true;
            break
        }
    }

    return isHave
}

Array.prototype.mySome = mySome;

let have1 = arrName.mySome((item) => item.name === '赵六');
let have2 = arrName.mySome((item) => item.name === '景七')
console.log(have1, have2)

Snipaste_2023-03-28_20-06-47.png

every

/**
 * every 方法
 * 功能 当所有值都符合条件则返回true 否则返回false
 */

function myEvery (callback) {
    if(typeof callback != 'function') {
        throw Error('不是一个方法')
    }

    let arr = this;
    let flag = true;
    for(const [index, value] of arr.entries()) {
        if (!callback(value, index, arr)) {
            flag = false;
            break
        }
    }

    return flag;
}

Array.prototype.myEvery = myEvery

const arr = [{name: '招录'}, {name: '招录'}, {name: '招录'}]

let targetMy = arr.myEvery(item => item.name == '招录')
let unTargetMy = arr.myEvery( item => item.name == '没有')
console.log('targetMy', targetMy);
console.log('unTargetMy', unTargetMy);

Snipaste_2023-03-29_08-54-37.png

用的比较少的方法

reduce

/**
 * reduce 数组方法
 * 功能  滚雪球遍历
 */

 function myReduce(callback, init) {
    if(Object.prototype.toString.call(callback) != '[object Function]') {
        throw Error('不是一个方法')
    }

    let arr = this;
    let start = init ? init : arr[0];
    let result = "";

    for (const [index, value] of arr.entries()) {
        if (init) {
            result = callback(start, value, index, arr);
        } else {
            if(index == 0) {
                continue;
            }
            result = callback(start, value, index, arr);   
        }
        start = result;
    }

    return result;
}

Array.prototype.myReduce = myReduce;
let target = [1, 2, 3, 4]
let result = target.myReduce((pre, current, index, arr)=> {
    return pre+= current;
}, -1);

console.log(result) //9

reduce.png

flat

/**
 * flat 
 * 功能 打平数组
 */
const arr = [1, [2], [3], [4,[8],9], [5, [6,[7]]]]

let origin = arr.flat()
console.log(origin)
console.log(' ==============与原的分割符号================')

function myFlat(number = 1) {
    let arr = this;
    let arrNew = [];
    if (number <= 0) {
        return arr;
    }

    // Infinity
    if (number === Infinity) {
        // return arrNew = JSON.stringify(arr).replace(/\[|\]/g, '').split(',');
        const cycleArray = (array) => {
            let arrTemp = [];
            for(let i = 0; i < array.length; i++) {
                if(Array.isArray(array[i])) {
                    arrTemp = arrTemp.concat(cycleArray(array[i]))
                } else {
                    arrTemp.push(array[i])
                }
            }
            return arrTemp
        }
        arrNew = cycleArray(arr);
        return arrNew;
    }

    for (let i = 0; i < arr.length; i++) {
        if(Array.isArray(arr[i])) {
            arrNew = arrNew.concat(arr[i].myFlat(number - 1));
        } else {
            arrNew.push(arr[i]);
        }
    }

    return arrNew
}

Array.prototype.myFlat = myFlat;

let target1 = arr.myFlat()
let target2 = arr.myFlat(2)
console.log(target1)
console.log('=========分割符===========')
console.log(target2)

Snipaste_2023-03-29_09-49-22.png