循环实现数组filter方法

        // 循环实现数组 filter 方法
        const selfFilter = function (fn, context){
            // 如果调用的地方使用箭头函数,这里的this岂不是不对了,那该怎么解决呢
            let arr = Array.prototype.slice.call(this)
            let filterArr = []
            for(let i = 0; i < arr.length; i++){
                if(!arr.hasOwnProperty(i)){
                    continue
                }
                fn.call(context, arr[i], i, this) && filterArr.push(arr[i])
            }
            return filterArr
        }
        
        const selfFilter2 = function (fn, context){
            return this.reduce((pre, cur, index) => {
                // 因为这里是return 的,所以不能像上面用&&实现
                return fn.call(context, cur, index, this) ? [...pre, cur] : [...pre]
            }, [])
        }
        
        // 循环实现数组的 some 方法
        const selfSome = function (fn, context){
            let arr = Array.prototype.slice.call(this)
            if(arr.length === 0){
                return false
            }
            for(let i = 0; i < arr.length; i++){
                if(!arr.hasOwnProperty(i)){
                    continue
                }
                let res = fn.call(context, arr[i], i, this)
                if(res){
                    return true
                }
            }
            return false
        }
        
        // 循环实现数组的 reduce 方法
        const selfReduce = function (fn, initialValue){
            let arr = Array.prototype.slice.call(this)
            let res
            let startIndex
            if(initialValue === undefined){
                // 找到第一个非空单位(真实)的元素和下标
                for(let i = 0; i < arr.length; i++){
                    if(!arr.hasOwnProperty(i)){
                        continue
                    }
                    startIndex = i
                    res = arr[i]
                    break
                }
            }else{
                res = initialValue
            }
            
            for(let i = ++startIndex || 0; i < arr.length; i++){
                if(!arr.hasOwnProperty(i)){
                    continue
                }
                res = fn.call(null, res, arr[i], i, this)
            }
            return res
        }
        
        // 使用 reduce 实现数组的 flat 方法
        // flat()方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。
        // 参数depth(可选),指定要提取嵌套数组的结构深度,默认值为1
        const selfFlat = function (depth = 1){
            let arr = Array.prototype.slice.call(this)
            if(depth === 0){
                return arr
            }
            return arr.reduce((pre, cur) => {
                //[]我之前记忆错了,这个应该是全部都是值,比如[cur],如果是数组的话,应该要先解构,比如[...pre]
                // 我之前一直是用的[...pre],却忘记了原本的用处,记录一波
                return Array.isArray(cur) ? [...pre, ...selfFlat.call(cur, depth - 1)] : [...pre, cur]
            }, [])
        }
        
        let arr1 = [1, 2, 3, 4]
        let arr2 = [1, 2, 3, [1, 5, 6, [2, 4, 5]]]
        // 看到上面方法的实现,我才想起,这些方法也可以用call来调用,call第一位
        
        let arrList = selfFilter.call(arr1, function(x){
            return x === 1
        })
        
        let arrList2 = selfFilter2.call(arr1, function(x){
            return x === 1
        })
        
        let arrList3 = selfSome.call(arr1, function(x){
            return x === 0
        })
        
        let arrList4 = selfReduce.call(arr1, function(total, res){
            return total + res
        }, 0)
        
        let arrList5 = selfFlat.call(arr2, Infinity)
        
        console.log(arrList)
        console.log(arrList2)
        console.log(arrList3)
        console.log(arrList4)
        console.log(arrList5)        

 

posted @ 2019-06-25 17:00  来亦何哀  阅读(1260)  评论(1编辑  收藏  举报