JS 中数组常用方法以及它的原理实现(二)

2020-07-13  本文已影响0人  泰然自若_750f

开始

上一节,对数组的5个API 进行了总结整理,下面接着根据MDN 上的顺序整理。

数组方法

Array.prototype.every()

作用

every() 方法测试一个数组内的所有元素是否都能通过某个指定函数的测试。它返回一个布尔值,数组为空返回true。

应用

console.log([].every(a=>a>1));//true
console.log([1,2,4].every(a=>a>1)) //false
console.log([1,2,4].every(a=>a>0)) //true
console.log([1,2,4]._every(function (a){ return a>this.n},{n:0}));//true

以前只知道传callback 参数,但是还有一个传参 thisArg,表示的是执行callback的this值,加上了thisArg参数,callback就不要用箭头函数了,因为箭头函数的this无法改变。

实现

思路

代码实现

Array.prototype._every=function (callback,thisArg) {
    if(typeof callback!='function')
    {
        throw new TypeError('callback is not a function')
    }
    
    let target=this,res=true;
    let context=thisArg ||this;
    for(let i=0;i<target.length;i++)
    {
        //有一项不满足就返回false
        if(!callback.call(context,target[i],i,target))
        {
             return false;
        }
    }
    return res;

}

测试

测试得到和原生相同的结果

console.log([]._every(a=>a>1));//true
console.log([1,2,4]._every(a=>a>1)) //false
console.log([1,2,4]._every(a=>a>0)) //true
console.log([1,2,4]._every(function (a){ return a>this.n},{n:0}));//true

Array.prototype.filter()

作用

filter() 方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。也就是数组内容过滤。

应用

var a=[1,2,3,5];
console.log(a.filter((item)=>item>2));//[3,5]
console.log(a.filter((item)=>item>this.n,{n:2})); //[]
console.log(a.filter(function(item){
    return item>this.n;
},{n:2}));// [3,5]

实现

下面就来具体实现该方法,其实很简单,就是对数组内容进行过滤,符合条件的加入新数组。

思路

代码实现

Array.prototype._filter=function (callback,thisArg) {
    
    if(typeof callback!='function')
    {
        throw new TypeError('callback is not a function')
    }
   //得到上下文
    let context=thisArg ||this;
    //返回新数组
    let target=this,res=[];
    for(let i=0;i<target.length;i++)
    {
        //符合条件的
        if(callback.call(context,target[i],i,target))
        {
             res.push(target[i])
        }
    }
    return res;
}

测试
总体来说很简单,就是要记住还有 thisArg 这个参数

var a=[1,2,3,5];
console.log(a._filter((item)=>item>2)); // [3,5]
console.log(a._filter((item)=>item>this.n,{n:2})); //[]
console.log(a._filter(function(item){
    return item>this.n;
},{n:2}))   //[3,5]

Array.prototype.find()

作用

find() 方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined。

注意只是返回的第一个值,其中还有一个Array.prototype.findIndex(),lian是返回的是第一个符合条件的索引,这个方法就不做介绍了。

实现

思路

代码实现

Array.prototype._find=function (callback,thisArg) {
    if(typeof callback!='function')
    {
        throw new TypeError('callback is not a function')
    }
    //上下文
    let context=thisArg || this;
    let target=this;
    for(let i=0;i<target.length;i++)
    {
        //有一项不满足就返回false
        if(callback.call(context,target[i],i,target))
        {
            return target[i];
        }
    }
    return undefined;
}

测试

很简单的一个API,不做太多解释了,findIndex 方法和它差不多,只是返回的是索引,没有符合条件的返回的是-1。

const found = array1._find(element => element > 1000);

console.log(found);

const found2=array1._find(function(element){
    return element>this.m;

},{m:100})
console.log(found2);

Array.prototype.flat()

作用

flat() 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。也就是实现数组的扁平化

这是个开发中很重要的一个API,也是相对实现难度较高的。

实例应用

console.log([1,2,[1,[3,[4]]],[2,[3,[4]]]].flat()); //[ 1, 2, 1, [ 3, [ 4 ] ], 2, [ 3, [ 4 ] ] ]
console.log([1,2,[1,[3,[4]]],[2,[3,[4]]]].flat(2)); //[ 1, 2, 1, 3, [ 4 ], 2, 3, [ 4 ] ]
console.log([1,2,[1,[3,[4]]],[2,[3,[4]]]].flat(Infinity)); //[ 1, 2, 1, 3, 4, 2, 3, 4 ]

实现

思路

Array.prototype._flat=function (deep) {
    //不传,不是大于1的数字都默认为1
    if(!deep ||typeof deep!='number'|| deep<1)
    {
        deep=1;
    }
    deep=Math.round(deep-0);
    let target=this,res=[];
   _toFlat(target,0,res);
    return res;
    function _toFlat(arr,n=0,res=[],state=false) {
        if(n>deep)
        {
            res.push(arr)
            return;
        }
        for(let i=0;i<arr.length;i++)
        {
            //是否是再次递归的标记,等到下一项,将 n置为0
            if(!state)
            {
                n=0;
            }
            
            if(arr[i] instanceof Array)
            {
                 n++;
                 //递归,传递递归标记为true
                 _toFlat(arr[i],n,res,true)
            }
            else{
                res.push(arr[i]);
            }
        }
        
    }


}

测试

三种情况

console.log([1,2,[1,[3,[4]]],[2,[3,[4]]]]._flat()); //[ 1, 2, 1, [ 3, [ 4 ] ], 2, [ 3, [ 4 ] ] ]
console.log([1,2,[1,[3,[4]]],[2,[3,[4]]]]._flat(2)); //[ 1, 2, 1, 3, [ 4 ], 2, 3, [ 4 ] ]
console.log([1,2,[1,[3,[4]]],[2,[3,[4]]]]._flat(Infinity)); //[ 1, 2, 1, 3, 4, 2, 3, 4 ]

数组原型上还有一个flatMap 方法,感觉毫无意义,不做介绍了。

Array.prototype.forEach()

forEach() 方法对数组的每个元素执行一次给定的函数。
这个方法也很常用,但是很简单,其实一个for循环就搞定了。

代码实现

Array.prototype._forEach=function(callback,thisArg){
    if(typeof callback!='function')
    {
        throw new TypeError('callback is not a function')
    }
    let context=thisArg ||this;
    for(let i=0;i<this.length;i++)
    {
        callback.call(context,this[i],i,this)
    }

}

测试

很简单的一个方法,简单测试一下即可

const array1 = ['a', 'b', 'c'];
array1._forEach(element => console.log(element));
//依次打印 a,b,c

结束

相关链接

上一篇 下一篇

猜你喜欢

热点阅读