美文网首页
JS 中数组常用方法以及它的原理实现(二)

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

作者: 泰然自若_750f | 来源:发表于2020-07-13 21:49 被阅读0次

    开始

    上一节,对数组的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无法改变。

    实现

    思路

    • 在数组原型上定义方法。
    • 数组为空永远返回true。
    • 传入了thisArg 参数要更改回调函数的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]
    

    实现

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

    思路

    • 在数组原型上定义方法。
    • 产生一个新数组,不能影响原数组的值。
    • 传入了thisArg 参数要更改回调函数的this指向。

    代码实现

    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是返回的是第一个符合条件的索引,这个方法就不做介绍了。

    实现

    思路

    • 在数组原型上定义该方法。
    • 两个参数,callback 和 thisArg(回调函数的this指向)。
    • 不要改变原数组。
    • 没有结果返回 undefined

    代码实现

    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 ]
    

    实现

    思路

    • 在数组原型上定义该方法。
    • 参数deep 代表扁平化的深度,有深度就会用递归。
    • 默认扁平化深度为1。
    • 使用 Infinity全部扁平化
    • 不会改变原数组
    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]);
                }
            }
            
        }
    
    
    }
    
    

    测试

    三种情况

    • 测试默认深度为1
    • 测试根据深度扁平化
    • 使用Infinity代表全部扁平化
    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
    

    结束

    相关链接

    相关文章

      网友评论

          本文标题:JS 中数组常用方法以及它的原理实现(二)

          本文链接:https://www.haomeiwen.com/subject/ouozcktx.html