看看Array.property.reduce是如何实现的

前言

由于自己对数组方法的reduce函数不熟悉, 所以就决定好好学习一下reduce方法。 在MDN好好看了它的用法。 并把它的polyfill好好阅读了一下。 以下是polyfill的实现, 和自己的注释。

正文

if(!Array.prototype.reduce){
    Object.defineProperty(Array.prototype, 'reduce', {
        value: function(callback/*, initialValue*/){
            if(this === null) { //判断是否是是null调用的reduce函数
                throw new TypeError('Array.prototype.reduce called on null or undefined')//使用===能判断出undefined?
            }
            if(typeof callback !== 'function') {//判断出入的参数是否是函数
                throw new TypeError(callback + 'is not a function' )
            }

            // 1. let o be ?? ToObject(this value)
            var o = Object(this) // 生成了一个数组o  //得到数组的副本

            // 2. let len be ? toLength( ? get(0, "lenght"))
            var len = o.length >>> 0   //获取数组的长度

            var k = 0   //当前索引
            var value   //最终返回的值

            if(arguments.length >= 2) { //如果有第二参数 (初始值), 从数组的第一个元素开始遍历
                value = arguments[1]  //将其赋值给value, 在做累加
            }else { //没有初始值
                while (k < len && !(k in o)){ //当数组是稀疏数组时, 判断数组当前是否有元素, 如果没有就索引加一
                    k++
                }

                //3. if len is 0 and initialValue is not present //如果数组为空, 且初始值不存在。抛出一个错误
                if( k >= len) {
                    throw new TypeError('Reduce of empty array with no initial value')
                }
                //把第一个非空元素的值给value, 并索引加一
                value = o[k++]
            }
            //以上都是为了获得value的初始值。 以便一下累加

            // 8. Repeat, while k < len
            while (k < len){
                // a. let Pk be ! ToString(k)
                // b. let Kpresent be ? HasProperty(0, Pk)
                // c. if kPresent is true, then
                //     i.  let kValue be ? Get(0, Pk)
                //     ii. let accumulator be ? call(
                //              callbackfn, undefined,
                //              << accumulator, kValue, k, o >>).
                if( k in o) {//如果当前索引处有值, 调用函数,累加
                    value = callback(value, o[k], k, o)// 传入4个参数, 第一个是value, 第二个当前值, 当前索引, 当前数组
                }
                k++
            }
            return value

        }
    })
}

/**
 * 整体说一下该polyfill函数的思路
 * 1. 如果javascript引擎不支持reduce函数, 那么久在Array的原型上定义了一个reduce的函数, 不过为啥要通过Object.defineProperty()来定义呢? 可以直接添加一个这样的函数就是了嘛
 * 2. 在添加的函数中,判断是否是null调用。 
 * 3. 判断第一个参数是是否为函数, 如果不是抛出错误
 * 4. 复制这个数组
 * 5. 得到数组的长度
 * 6. 设置当前索引
 * 7. 定义value变量
 * 8. 给value设置初始值, 如果传入了第二参数, 就将其设置为value, 否则找到第一个非空元素设置其为value的值
 * 9. 循环调用callback累加, 其中会通过in 判断是否为空, 如果为空跳过调用callback、
 * 10. 返回value
 */

思考


  这里是限定了不让undefined和null调用reduce, 
  限定了传入的callback必须为函数
  限定了如果没有传入初始值, 且数组用没有第一个非空元素会报错

  疑惑:如果出现其他的情况时怎么处理的, 比如用obj去调用它。 
  答案:仔细想想, 只要能给value值设置初始值, 就不会报错,就能返回一个value。否则就会报错。 不管使用什么方式调用, 只要不是undefined和null都能o.length去读取该属性, 返回一个真实的length或者undefined. 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值