JS reduce方法源码解析

2,396 阅读2分钟

前言

最近在百度上搜索对数组内的对象去重时,突然发现有的大佬使用reduce方法去重,这个时候就觉得很不可思议了,因为以前可能是使用reduce方法比较多,所以就特意研究了一下

文档

我们首先看看MDN上是怎么介绍的reduce方法吧,reduce函数主要是接收两个参数,即

    reduce(callback(accumulator, currentValue[, currentIndex, array])[, initvalue])
    // 注释: 中括号括起来的表示非必填参数

参数

  1. callback 是一个回调函数,接收四个参数,其中第一个和第二个是必填项,第三个和第四个为非必填,
    1. accumulator:累计器累计回调的返回值
    2. currentValue:当前项的值
    3.currentIndex: 当前项的索引 
    4. array:是调用reduce函数的数组
    
  2. initvalue: 是accumulator的初始值,非必传

返回值

  1. 返回函数累计处理的结果

解析

  1. 首先我们来说一下,当reduce的第二个参数传的时候,那么callback的第一个参数就会去initvalue这个值,当reduce函数的第二个参数initvalue不传的时候,callback的第一个参数accu就会取当前数组的第一项

所以我们来尝试写一下源码

Array.prototype.myReducer = function(callback, initvalue) {
    var len = this.length 
    var pre = initvalue
    var i = 0
    if(pre == undefined) {
        pre = this[0];
        i = 1
    } 
    for(i; i < len; i++) {
        pre = callback(pre, this[i], i, this)
    }
    return pre 
}

大致上就是这样的

功能

  1. 首先我们先来看求和,废话不多说,直接上代码
let arr = [1, 2, 3, 4]
arr.reduce((sum, current) => sum + current)

我们可以看到返回值是10,这也是我们使用的最多的求和功能
2. 去重,下面我们来看下去重功能,判断如果age相同,则视为对象相同

let arr2 = [
    {
        name: 'zhangsna',
        age: 14
    },
    {
        name: 'lisi',
        age: 14
    }
]
let arr3 = {} // 辅助数组
let arr4 = arr2.reduce((sum, current) => {
    if (!arr3[current.age]) { // 判断当前age是否已经在arr3里面
        // 如果不在
        arr3[current.age] = true // 则将当前age值设置true(可以是其他的)
        sum.push(current) // 然后push进当前数组
    }
    return sum
}, [])
console.log(arr4)

这样我们就可以很轻松的实现了

实现真正的数组内的对象去重

reduce.js 

let arr6 = [
    {
        name: 'zhangsna',
        age: 14
    },
    {
        name: 'zhangsna',
        age: 14
    }
]
let arr7 = {}
let arr5 = arr6.reduce((sum, current) => {
    if (!arr7[JSON.stringify(current)]) {
        arr7[JSON.stringify(current)] = true
        sum.push(current)
    }
    return sum
}, [])
console.log(arr5)

这样我们就实现比较轻松高效的对象去重了