js的reduce實(shí)現(xiàn)以及使用場(chǎng)景

MDN鎮(zhèn)文
https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

手寫(xiě)實(shí)現(xiàn)reduce

實(shí)現(xiàn)方式一

Array.prototype.reduce = function (fn, init) {
    if (typeof fn !== 'function') {
        throw new TypeError('xxx');
    }

    initArr = this;
    arr = initArr.concat();
    if (init) arr.unshift(init);
    let index, newVal;
    while (arr.length > 1) {
        index = initArr.length - arr.length + 1;
        newVal = fn.call(null, arr[0], arr[1], index, initArr);

        arr.splice(0, 2, newVal)
    }

    return newVal
}

實(shí)現(xiàn)方式二 (遞歸)

const reduceHelper = (fn, acc, idx, array) => {
    if (array.length === 0) return acc
    const [head, ...tail] = array
    idx++
    return reduceHelper(fn, fn(acc, head, idx, array), idx, tail)
}

Array.prototype.myReduce = function (cb, initialValue) {
    const array = this
    const [head, ...tail] = array
    const startIndex = initialValue ? -1 : 0

    return initialValue ? reduceHelper(cb, initialValue, startIndex, array) : reduceHelper(cb, head, startIndex, tail)
}

應(yīng)用場(chǎng)景

一: 累加

const sum = arr => arr.reduce((acc, val) => acc + val, 0);
sum([1, 2, 3]);

二: 計(jì)數(shù)器

let names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];
let nameNum = names.reduce((pre, cur) => {
    if (cur in pre) {
        pre[cur]++
    } else {
        pre[cur] = 1
    }
    return pre
}, {})
console.log(nameNum); // //{Alice: 2, Bob: 1, Tiff: 1, Bruce: 1}

三: 數(shù)組扁平化

const deepFlatten = arr =>
    arr.reduce((a, v) => a.concat(Array.isArray(v) ? deepFlatten(v) : v), []);
console.log(deepFlatten([1, [2, [3, 4, [5, 6]]]]));

四: 生成斐波那契數(shù)列

const fibonacci = n => Array(n).fill(0).reduce((acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), []);
console.log(fibonacci(5));

五: 中間件

redux中經(jīng)典的compose函數(shù)中運(yùn)用了這種方式, 通過(guò)對(duì)中間件的重重層疊, 在真正發(fā)起action的時(shí)候觸發(fā)函數(shù)執(zhí)行.

const dispatch = action => {
    console.log('action', action);
    return action;
}
const middleware1 = dispatch => {
    return action => {
        console.log("middleware1");
        const result = dispatch(action);
        console.log("after middleware1");
        return result;
    }
}
const middleware2 = dispatch => {
    return action => {
        console.log("middleware2");
        const result = dispatch(action);
        console.log("after middleware2");
        return result;
    }
}
const middleware3 = dispatch => {
    return action => {
        console.log("middleware3");
        const result = dispatch(action);
        console.log("after middleware3");
        return result;
    }
}
const compose = middlewares => middlewares.reduce((a, b) => {
    return function (args) {
        return a(b(args))
    }
})

const middlewares = [middleware1, middleware2, middleware3];
const afterDispatch = compose(middlewares)(dispatch);

// const afterDispatch = middleware1(middleware2(middleware3(dispatch)));

const testAction = arg => {
    return { type: "TEST_ACTION", params: arg };
};
afterDispatch(testAction("1111"));

六: 對(duì)象空值判斷

let school = {
    name: 'Hope middle school',
    created: '2001',
    classes: [
        {
            name: '三年二班',
            teachers: [
                { name: '張二蛋', age: 26, sex: '男', actor: '班主任' },
                { name: '王小妞', age: 23, sex: '女', actor: '英語(yǔ)老師' }
            ]
        },
        {
            name: '明星班',
            teachers: [
                { name: '歐陽(yáng)娜娜', age: 29, sex: '女', actor: '班主任' },
                { name: '李易峰', age: 28, sex: '男', actor: '體育老師' },
                { name: '楊冪', age: 111, sex: '女', actor: '藝術(shù)老師' }
            ]
        }
    ]
};
// 常規(guī)做法
school.classes &&
    school.classes[0] &&
    school.classes[0].teachers &&
    school.classes[0].teachers[0] &&
    school.classes[0].teachers[0].name
// reduce方法
const get = (p, o) => p.reduce((xs, x) => (xs && xs[x] ? xs[x] : null), o);
get(['classes', 0, 'teachers', 0, 'name'], school); // 張二蛋

七: 過(guò)濾屬性

根據(jù)給出的鍵值來(lái)遍歷易阳,比較對(duì)象中是否存在相同鍵值的的值,然后通過(guò)逗號(hào)表達(dá)式把賦值后的對(duì)象賦給下一個(gè)的初始值

const pick = (obj, arr) =>
    arr.reduce(function (acc, curr) {
        if (curr in obj) {
            acc[curr] = obj[curr]
            return acc;
        }
    }, {});

// 也可以簡(jiǎn)寫(xiě)成
const pick2 = (obj, arr) =>
    arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {});
pick({ a: 1, b: '2', c: 3 }, ['a', 'c']);

八: 分組

首先通過(guò)map計(jì)算出所有的鍵值巍杈,然后再根據(jù)建值進(jìn)行歸類(lèi)

const groupBy = (arr, func) =>
    arr.map(typeof func === 'function' ? func : val => val[func])
    .reduce((acc, val, i) => {
        acc[val] = (acc[val] || []).concat(arr[i]);
        return acc;
    }, {});
groupBy([6.1, 4.2, 6.3], Math.floor);
groupBy(['one', 'two', 'three'], 'length');

九: 數(shù)組刪除指定位置的值

首先根據(jù)filter函數(shù)過(guò)濾出數(shù)組中符合條件的值坪稽,然后使用reduce在原數(shù)組中刪除符合條件的值曼玩,可以得出最后arr的值變成了[1, 3]

const remove = (arr, fn) =>{
    return arr.filter(fn).reduce((acc, cur) => {
        arr.splice(arr.indexOf(cur), 1);
        return acc.concat(cur);
    }, []);
}
const arr = [1, 7, 3, 4, 8];
console.log(remove(arr, n => n % 3 == 1))
console.log(arr)

十: 字母游戲

reduce負(fù)責(zé)篩選出每一次執(zhí)行的首字母,遞歸負(fù)責(zé)對(duì)剩下字母的排列組合窒百。

const anagrams = str => {
    if (str.length <= 2) {
        return str.length === 2 ? [str, str[1] + str[0]] : str;
    }
    return str.split("").reduce((acc, letter, i) => {
        return acc.concat(anagrams(str.slice(0, i) + str.slice(i + 1)).map(val => letter + val));
    }, []);
}

anagrams("abc");

十一: 排序

const orderBy = (arr, props, orders) =>
    [...arr].sort((a, b) =>
        props.reduce((acc, prop, i) => {
            if (acc === 0) {
                const [p1, p2] = orders && orders[i] === 'desc' ? [b[prop], a[prop]] : [a[prop], b[prop]];
                acc = p1 > p2 ? 1 : p1 < p2 ? -1 : 0;
            }
            return acc;
        }, 0)
    );
const users = [{ name: 'fred', age: 48 }, { name: 'barney', age: 36 }, { name: 'fly', age: 26 }];
console.log(orderBy(users, ['age'], ['desc']));
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末黍判,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子篙梢,更是在濱河造成了極大的恐慌顷帖,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異贬墩,居然都是意外死亡榴嗅,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)陶舞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)录肯,“玉大人,你說(shuō)我怎么就攤上這事吊说÷塾剑” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵颁井,是天一觀的道長(zhǎng)厅贪。 經(jīng)常有香客問(wèn)我,道長(zhǎng)雅宾,這世上最難降的妖魔是什么养涮? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮眉抬,結(jié)果婚禮上贯吓,老公的妹妹穿的比我還像新娘。我一直安慰自己蜀变,他們只是感情好悄谐,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著库北,像睡著了一般爬舰。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上寒瓦,一...
    開(kāi)封第一講書(shū)人閱讀 52,457評(píng)論 1 311
  • 那天情屹,我揣著相機(jī)與錄音,去河邊找鬼杂腰。 笑死垃你,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的喂很。 我是一名探鬼主播惜颇,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼恤筛!你這毒婦竟也來(lái)了官还?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤毒坛,失蹤者是張志新(化名)和其女友劉穎望伦,沒(méi)想到半個(gè)月后林说,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡屯伞,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年腿箩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片劣摇。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡珠移,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出末融,到底是詐尸還是另有隱情钧惧,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布勾习,位于F島的核電站浓瞪,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏巧婶。R本人自食惡果不足惜乾颁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望艺栈。 院中可真熱鬧英岭,春花似錦、人聲如沸湿右。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)诅需。三九已至漾唉,卻和暖如春荧库,著一層夾襖步出監(jiān)牢的瞬間堰塌,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工分衫, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留场刑,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓蚪战,卻偏偏與公主長(zhǎng)得像牵现,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子邀桑,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360

推薦閱讀更多精彩內(nèi)容

  • 第5章 引用類(lèi)型(返回首頁(yè)) 本章內(nèi)容 使用對(duì)象 創(chuàng)建并操作數(shù)組 理解基本的JavaScript類(lèi)型 使用基本類(lèi)型...
    大學(xué)一百閱讀 3,238評(píng)論 0 4
  • 一瞎疼、數(shù)組定義 array() 1、索引數(shù)組 在一個(gè)變量中壁畸,存儲(chǔ)一個(gè)或多個(gè)值贼急。數(shù)組中的每一個(gè)元素都有一個(gè)訪問(wèn)ID茅茂,根...
    竹與豆閱讀 535評(píng)論 0 0
  • 第一章 錯(cuò)誤處理: 錯(cuò)誤: 程序運(yùn)行過(guò)程中,導(dǎo)致程序無(wú)法正常執(zhí)行的現(xiàn)象(即bug) 現(xiàn)象: 程序一旦出錯(cuò)太抓,默認(rèn)會(huì)報(bào)...
    fastwe閱讀 1,121評(píng)論 0 1
  • 1.strlen()與mb_strlen()的作用分別是什么? strlen()和mb_strlen()都是作用于...
    落魄PHP女程序員閱讀 357評(píng)論 0 2
  • 函數(shù)和對(duì)象 1空闲、函數(shù) 1.1 函數(shù)概述 函數(shù)對(duì)于任何一門(mén)語(yǔ)言來(lái)說(shuō)都是核心的概念。通過(guò)函數(shù)可以封裝任意多條語(yǔ)句走敌,而且...
    道無(wú)虛閱讀 4,581評(píng)論 0 5