面试官:请你实现一下map / filter / reduce | 数据基础方法的模块化实现

数组基础方法的实现是前端面试常问的点,有时我们感觉自己写出了解法面试官却不满意,那是因为我们只注重了功能实现,而未考虑模块化开发导致的,下面介绍如何实现并封装数组常用的多个方法。

首先,我们定义一个类,这个类继承自Array类,所以Array类的方法它也都包括,我们可以使用new通过该类构建一个数组实例,这个实例和普通数组没有分别。

class ArrayExent extends Array{
	test(){
        console.log("新定义的方法被调用了");
    }
}

let arrTan = new ArrayExent(1,2,3);
console.log(arrTan) // [1 ,2, 3]

可以看到,通过new ArrayExent创建的数组实例是就是一个正常数组。

另外,我们在ArrayExent上定义了方法test,这个方法会写到ArrayExent的原型对象中去,这是ArrayExent数组的不同之处,它比正常数组多了一个方法test,ArrayExent数组实例可以调用ArrayExent类原型对象上的方法,因为它是ArrayExent的实例。

arrTan.test(); // 新定义的方法被调用了

所以,我们只要将方法写到ArrayExent类中,就可以拥有可以调用我们自定义方法的数组实例了。

对于数据的基础方法这里就不多做介绍,直接上实现。

class ArrayExent extends Array{
    test(){
        console.log("新定义的方法被调用了");
    }
    mapExent(callBackFun){
        // 调用传入的函数 映射所有的项到新数组
        let arrRes = [];
        for(let i = 0; i < this.length; i++){
            arrRes[i] = callBackFun(this[i], i, this);
        }
        return arrRes;
    }
    everyExent(callBackFun){
        // 调用传入的函数 全部返回true则返回true
        let res = true;
        for(let i = 0; i < this.length; i++){
            res = res && callBackFun(this[i], i, this);
        }
        return res;
    }
    someExent(callBackFun){
        // 调用传入的函数 一个返回true则返回true
        let res = false;
        for(let i = 0; i < this.length; i++){
            res = res || callBackFun(this[i], i, this);
        }
        return res;
    }
    filterExent(callBackFun){
        // 返回true则为新数组的一部分
        let arrRes = [];
        for(let i = 0; i < this.length; i++){
            if(callBackFun(this[i], i, this)) {
                arrRes.push(this[i]);
            }
        }
        return arrRes;     
    }
    reduceExent(callBackFun, pre = -1){
        // 调用传入的函数 对pre进行处理
        let i = 0;
        if(pre === -1){
            pre = this[0];
            i++;
        }
        for(; i < this.length; i++){
            pre = callBackFun(pre, this[i], i, this);
        }
        return pre;
    }
}
let arrTan = new ArrayExent(1,2,3);

// every
let everyRes1 = arrTan.everyExent((ele,i,arr)=>{
    return ele !== 2;
})
let everyRes2 = arrTan.everyExent((ele,i,arr)=>{
    return ele !== 4;
})
console.log(everyRes1, everyRes2); // false true

// filter
let filterRes1 = arrTan.filterExent((ele,i,arr)=>{
    return ele === 2;
})
let filterRes2 = arrTan.filterExent((ele,i,arr)=>{
    return ele !== 2;
})
console.log(filterRes1, filterRes2); // [2] [1, 3]

//map
let mapRes1 = arrTan.mapExent((ele,i,arr)=>{
    return ele + 1;
})
console.log(mapRes1); // [2, 3, 4]

//some
let someRes1 = arrTan.someExent((ele,i,arr)=>{
    return ele !== 2;
})
let someRes2 = arrTan.someExent((ele,i,arr)=>{
    return ele === 4;
})
console.log(someRes1, someRes2); // true false

//reduce()
let reduceRes1 = arrTan.reduceExent((pre, ele,i,arr)=>{
    return ele + pre;
}, 10)
let reduceRes2 = arrTan.reduceExent((pre, ele,i,arr)=>{
    return ele + pre;
})
console.log(reduceRes1, reduceRes2); // 16 6
上一篇:04.URL路径访问与模块控制器之间的关系


下一篇:冒泡排序实现