Javascript数组常用方法重写之find,findIndex,filter,forEach

21 篇文章 0 订阅
20 篇文章 0 订阅

概要

我们在前端开发过程中,经常使用到各种数组的原生方法。为了更好的理解和使用这些原生方法,所以笔者试着重写了这些方法,并实现了相同的功能。

本文主要对find,findIndex,filter,forEach这四个原型方法进行重写。

代码实现

由于新方法也要定义在原型链上,为了避免重复,所以本文参考C#的LINQ方法命名。具体如下:

原型方法名称重写后的方法名称
findFirst
findIndexfirstIndex
filterWhere
forEachEach

find 方法重写

实现功能:在数组内找到第一个符合搜索条件的元素,并返回该元素,如果没有符合条件的元素,返回undefined。

不对原数组内元素进行修改,返回值如果是JS对象,直接返回数组内元素,不对返回值进行克隆。

Array.prototype.First = function(fn){
    var self = this;
    var length = self.length;
    var newThis = arguments[1] || window; 
    var item;   
    for(var i=0; i<length; ++i){
        item = deepClone(self[i]);
        var res = fn.apply(newThis,[item, i, self]);
        if (res){
            return self[i];
        }
    }
    return;
}
  1. 和JS原生的find方法一样,固定参数只有一个,类型为Fucntion,该方法返回一个bool值。
  2. 根据ES5的this使用规则,谁调用该方法,该方法内的this指向谁,所以该方法内的this指向未来调用该方法的数组对象。
  3. 和JS原生的find方法一样,First方法的第二个参数是可选的。它是新新的this,如果该参数不为空,则First方法内回调方法的this指向该对象。
  4. 遍历数组,数组元素在使用之前进行深度克隆,避免使用中被篡改,deepClone方法详见附录。
  5. 调用回调方法fn,检查传入的元素是否满足搜索条件。其中,fn方法的每个参数都是可选的,并且需要固定fn方法内的this,所以采用apply方法进行调用。
  6. 找到第一个符合搜索条件的元素后立刻返回。

findIndex 方法重写

实现功能:在数组内找到第一个符合搜索条件的元素,并返回该元素的索引,如果没有符合条件的元素,返回 -1。

不对原数组内元素进行修改,返回值如果是JS对象,直接返回数组内元素,不对返回值进行克隆。

Array.prototype.FirstIndex = function(fn){
    var self = this;
    var length = self.length;
    var newThis = arguments[1] || window; 
    var item;   
    for(var i=0; i<length; ++i){
        item = deepClone(self[i]);
        var res = fn.apply(newThis,[item, i, self]);
        if (res){
            return i;
        }
    }
    return -1;
}
  1. 和JS原生的findIndex方法一样,固定参数只有一个,类型为Fucntion,该方法返回一个bool值。
  2. 根据ES5的this使用规则,谁调用该方法,该方法内的this指向谁,所以该方法内的this指向未来调用该方法的数组对象。
  3. 和JS原生的findIndex方法一样,FirstIndex方法的第二个参数是可选的。它是新新的this,如果该参数不为空,则FirstIndex方法内回调方法的this指向该对象。
  4. 遍历数组,数组元素在使用之前进行深度克隆,避免使用中被篡改,deepClone方法详见附录。
  5. 调用回调方法fn,检查传入的元素是否满足搜索条件。其中,fn方法的每个参数都是可选的,并且需要固定fn内的方法内的this,所以采用apply方法进行调用。
  6. 找到第一个符合搜索条件的元素后立刻返回该元素的索引。

filter 方法重写

实现功能:在数组内找到第全部符合搜索条件的元素,并返以数组的形式返回所有符合条件的元素,如果没有符合条件的元素,返回空数组。

不对原数组内元素进行修改,返回值如果是JS对象,直接返回数组内元素,不对返回值进行克隆。

Array.prototype.Where = function(fn){
    var self = this;
    var length = self.length;
    var newThis = arguments[1] || window; 
    var res = [];
    var item;
    for(var i=0; i<length; ++i){
        item = deepClone(self[i]);
        var filter = fn.apply(newThis,[item, i, self]);
        filter && res.push(self[i]);
    }
    return res;
}
  1. 和JS原生的filter方法一样,固定参数只有一个,类型为Fucntion,该方法返回一个bool值。
  2. 根据ES5的this使用规则,谁调用该方法,该方法内的this指向谁,所以该方法内的this指向未来调用该方法的数组对象。
  3. 和JS原生的filter方法一样,Where方法的第二个参数是可选的。它是新新的this,如果该参数不为空,则Where方法内回调方法的this指向该对象。
  4. 遍历数组,数组元素在使用之前进行深度克隆,避免使用中被篡改,deepClone方法详见附录。
  5. 调用回调方法fn,检查传入的元素是否满足搜索条件,满足条件的放入返回数组中。其中,fn方法的每个参数都是可选的,并且需要固定fn方法内的this,所以采用apply方法进行调用。

forEach方法重写

实现功能:遍历数组内每个元素,并执行传入的方法,无返回值。不对原数组内元素进行修改。

Array.prototype.Each = function(fn){
    var self = this;
    var length = self.length;
    var newThis = arguments[1] || window; 
    var item;
    for(var i=0; i<length; ++i){
        item = deepClone(self[i]);
        fn.apply(newThis, [item, i, self]);
    }
    return;
}
  1. 和JS原生的filter方法一样,固定参数只有一个,类型为Fucntion,该方法无返回值。
  2. 根据ES5的this使用规则,谁调用该方法,该方法内的this指向谁,所以该方法内的this指向未来调用该方法的数组对象。
  3. 和JS原生的forEach方法一样,Each方法的第二个参数是可选的。它是新新的this,如果该参数不为空,则方法内回调方法的this指向该对象。
  4. 遍历数组,数组元素在使用之前进行深度克隆,避免使用中被篡改,deepClone方法详见附录。
  5. 调用回调方法fn,检查传入的元素是否满足搜索条件,满足条件的放入返回数组中。其中,fn方法的每个参数都是可选的,并且需要固定fn方法内的this,所以采用apply方法进行调用。

附录

function deepClone(origin, map = new WeakMap()){
    if (origin == undefined || typeof origin !== "object"){
        return origin;
    }
    if (origin instanceof Date){
        return new Date(origin);
    }
    if (origin instanceof RegExp){
        return new RegExp(origin);
    }
    var copied = map.get(origin);
    if (!!copied){
        return copied;
    }
    let target = new origin.constructor();
    map.set(origin, target);
    let keys = Reflect.ownKeys(origin);
    for(let key of keys){  
        target[key] = deepClone(origin[key], map);
    }
    return target;
} 
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值