深入es6数组方法原理

322 阅读1分钟

es6的方法一直在用,尤其是数组方法,简化了很多对数组的操作。但是对于其实现原理,一直也没有深究,最近在项目中,遇到了一个需求:需要对之前的数组元素进行过滤,过滤后的元素需要重新整合属性值,且不改变原有数组的元素。在用filter方法的时候,发现会改变其原有数组中的元素,遂萌生了自己重写该方法的想法,即产生了该篇文章。这篇文章会分析es6语法中数组的常用方法,并自己手动实现这些方法。 1. forEach方法:

    Array.prototype.MyForEach = function(cb){
        var _arr = this
        var _len = _arr.length
        var _this = arguments[1] || window
        for(let i = 0; i<_len; i++){
            cb.apply(_this,[_arr[i],i, _arr])
        }
    }

2. map方法:

    Array.prototype.MyMap = function(cb){
        var _arr = this
        var _len = _arr.length
        var _this = arguments[1] || window
        var _newArr = []
        var res
        for(let i = 0; i < _len; i++){
            // ! 这样可以保证不改变原来的数组,对原来的map方法进行了改进
            let newVal = deepClone(_arr[i])
             res = cb.apply(_this,[newVal,i,_arr])
            if(res){
                _newArr.push(res)
            }
        }
        return _newArr
    }

3. filter方法:

    Array.prototype.MyFilter = function(cb){
        var _arr = this
        var _len = _arr.length
        var _this = arguments[1] || window
        var _newArr = []
        for(let i = 0; i<_len; i++){
        // ! 这样可以保证不改变原来的数组,对原来的filter方法进行了改进
            var newVal = deepClone(_arr[i])
            if(cb.apply(_this,[newVal,i,_arr])){
                _newArr.push(newVal)
            }
        }
        return _newArr
    }

4. every方法:

    Array.prototype.MyEvery = function(cb){
        var _arr = this
        var _len = _arr.length
        var _this = arguments[1] || window
        let res = true
        for(let i = 0; i<_len; i++){
            if(!cb.apply(_this,[_arr[i],i,_arr])){
                res = false
                break
            }
        }
        return res
    }

5. some方法:

    Array.prototype.MySome = function(cb){
        var _arr = this
        var _len = _arr.length
        var _this = arguments[1] || window
        let res = false
        for(let i = 0; i<_len; i++){
            if(cb.apply(_this,[_arr[i],i,_arr])){
                res = true
                break
            }
        }
        return res
    }

6. find方法:

  Array.prototype.MyFind = function(cb){
    var _arr = this
    var _len = _arr.length
    var _this = arguments[1] || window
    var res
    for(let i = 0; i < _len; i++){
        if(cb.apply(_this,[_arr[i],i,_arr])){
            res =  _arr[i]
            break
        }
    }
    return res
}

7. findIndex方法:

 Array.prototype.MyFindIndex = function(){
    var _arr = this
    var _len = _arr.length
    var _this = arguments[1] || window
    var res
    for(let i = 0; i < _len; i++){
        if(cb.apply(_this,[_arr[i],i,_arr])){
            res =  i
            break
        }
    }
    return res
}

8. reduce方法:

Array.prototype.MyrReduce = function(cb){
    var _arr = this
    var _len = _arr.length
    var initial = arguments[1]
    for(let i = 0; i < _len; i++){
        if(i === 0 && initial === undefined){
            initial = _arr[0]
        }else{
            initial = cb.apply(window,[ initial, _arr[i], i, _arr ])
        }
    }

    return initial
}

9. reduceRight方法:

Array.prototype.MyReduceRight = function(cb){
    var _arr = this
    var _len = _arr.length
    var initial = arguments[1]
    for(let i = _len - 1; i >= 0; i--){
        if(i === _len - 1 && initial === undefined){
            initial = _arr[_len - 1]
        }else{
            initial = cb.apply(window,[ initial, _arr[i], i, _arr ])
        }
    }

    return initial
}

10. 辅助方法deepClone:

// 对象的深拷贝
function deepClone(cloneObj,target){
    var _target = target||  {}
    for(let key in cloneObj){
        // hasOwnProperty判断是否是对象自身属性,不包括继承的属性
        if(cloneObj.hasOwnProperty(key)){
            if(typeof cloneObj[key] === 'object' && cloneObj[key] !== null){
                _target[key] =  Object.prototype.toString.call(cloneObj) === '[object Array]' ? [] : {}
                deepClone(cloneObj[key],_target[key])
            }else{
                _target[key] = cloneObj[key] 
            }
        }
    }
    return _target
}