假設有這樣一個數組:數組
let person = [ {id: 0, name: "小明"}, {id: 1, name: "小張"}, {id: 2, name: "小李"}, {id: 3, name: "小孫"}, {id: 1, name: "小周"}, {id: 2, name: "小陳"}, ]
咱們想去掉數組中id重複的對象,好比一樣id爲2的兩個對象——函數
{id: 2, name: "小李"}和{id: 2, name: "小陳"} (去掉任何一個均可以)
咱們該如何去作呢?spa
事實上,對於數組對象,傳統的去重方法無能爲力,至於forEach()、filter()等迭代方法也很差使;真正能作到優雅去重的,是ES5新增長的一個方法——reduce()code
reduce()方法接收一個回調函數做爲第一個參數,回調函數又接受四個參數,分別是:對象
1.previousValue => 初始值或上一次回調函數疊加的值;blog
2. currentValue => 本次回調(循環)將要執行的值;索引
3. index =>「currentValue」的索引值;回調函數
4. arr => 數組自己;it
reduce()方法返回的是最後一次調用回調函數的返回值;io
let log = console.log.bind(console); let arr = [1,2,3,4,5,6]; arr = arr.reduce((previousValue, currentValue) => { return previousValue + currentValue; //返回的是最後一次調用回調函數的值,15+6; }) log(arr); // 21
能夠看出,上面代碼的最終結果就是1+2+3+4+5+6 = 21;
此外,reduce還能夠接收第二參數initialValue,用來聲明回調函數(第一個參數)的previousValue的類型和初始值;
let log = console.log.bind(console); let arr = [1,2,3,4,5,6]; arr = arr.reduce((previousValue,currentValue) => { return previousValue + currentValue; },0) //指定cur的類型爲Number而且初始值爲0,當設爲1時,最終打印的值爲22
log(arr); // 21
須要注意的是,若是設置了initialValue的值,第一次執行回調函數的previousValue的值等於initialValue,此時查看當前索引(index)爲0;但若是不設置initialValue的值,previousValue的值爲數組的第一項,而且索引值(index)爲1;也就是說,不設置初始值的話reduce()方法實際是從第二次循環開始的!
如今讓咱們回到文章開頭的那個數組:
let log = console.log.bind(console); let person = [ {id: 0, name: "小明"}, {id: 1, name: "小張"}, {id: 2, name: "小李"}, {id: 3, name: "小孫"}, {id: 1, name: "小周"}, {id: 2, name: "小陳"}, ]; let obj = {}; person = person.reduce((cur,next) => { obj[next.id] ? "" : obj[next.id] = true && cur.push(next); return cur; },[]) //設置cur默認類型爲數組,而且初始值爲空的數組 log(person);
打印person後,咱們就能夠獲得去重後的數組。
固然, redecu()除了累加和去重外,功能還有不少,好比能夠扁平化多維數組——
var flattened = [[0, 1], [2, 3], [4, 5]].reduce(function(a, b) { return a.concat(b); }, []); // [0,1,2,3,4,5]
再說句題外的,提到去重,不少人都會想到ES6的Set;不過根據個人實驗,Set仍是適合對基本類型的去重,若是Set中的每一項是對象的話,是不會去重的,j即便有的對象如出一轍——
let arr = new Set([ {id: 0, name: "小明"}, {id: 0, name: "小明"}, {id: 0, name: "小明"}, {id: 0, name: "小明"} ]); console.log([...arr]); //依舊是這4個對象