版权声明:杨念 https://blog.csdn.net/qq_34178990/article/details/81225109
前言
由于自己对数组方法的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.