日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

JavaScript Reduce使用詳解

瀏覽:358日期:2023-10-03 15:59:27

JavaScript Reduce使用詳解

學會這一個技巧 Reduce 讓你開啟編程新世界

Learning This Reduce Skill and a Whole New World Will Open up for You 🎉

reduce 可謂是 JS 數組方法最靈活的一個,因為可以替代數組的其他方法,比如 map / filter / some / every 等,也是最難理解的一個方法,lodash 很多方法也可以用其實現,學會 reduce 將給與開發者另一種函數式(Functional)、聲明式(Declarative)的視角解決問題,而不是以往的過程式(Procedual)或命令式(Imperative)

其中一個難點在于判斷 acc 即 accumulation 的類型以及如何選擇初始值,其實有個小技巧,可以幫助我們找到合適的初始值,我們想要的返回值的類型和 acc 類型需要是一樣的,比如求和最終結果是數字,則 acc 應該是數字類型,故其初始化必定是 0。

下面開始鞏固對 reduce 的理解和用法。

map

根據小技巧,map 最終返回值是數組,故 acc 也應該是一個數組,初始值使用空數組即可。

/** * Use `reduce` to implement the builtin `Array.prototype.map` method. * @param {any[]} arr * @param {(val: any, index: number, thisArray: any[]) => any} mapping * @returns {any[]} */function map(arr, mapping) { return arr.reduce((acc, item, index) => [...acc, mapping(item, index, arr)], []);}

測試

map([null, false, 1, 0, ’’, () => {}, NaN], val => !!val);// [false, false, true, false, false, true, false]filter

根據小技巧,filter 最終返回值也是數組,故 acc 也應該是一個數組,使用空數組即可。

/** * Use `reduce` to implement the builtin `Array.prototype.filter` method. * @param {any[]} arr * @param {(val: any, index: number, thisArray: any[]) => boolean} predicate * @returns {any[]} */function filter(arr, predicate) { return arr.reduce((acc, item, index) => predicate(item, index, arr) ? [...acc, item] : acc, []);}

測試

filter([null, false, 1, 0, ’’, () => {}, NaN], val => !!val);// [1, () => {}]some

some 當目標數組為空返回 false,故初始值為 false。

function some(arr, predicate) { return arr.reduce((acc, val, idx) => acc || predicate(val, idx, arr), false)}

測試:

some([null, false, 1, 0, ’’, () => {}, NaN], val => !!val);// truesome([null, false, 0, ’’, NaN], val => !!val);// false

附帶提醒,二者對結果沒影響但有性能區別,acc 放到前面因為是短路算法,可避免無謂的計算,故性能更高。

acc || predicate(val, idx, arr)

predicate(val, idx, arr) || accevery

every 目標數組為空則返回 true,故初始值為 true

function every(arr, predicate) { return arr.reduce((acc, val, idx) => acc && predicate(val, idx, arr), true)}findIndex

findIndex 目標數組為空返回 -1,故初始值 -1。

function findIndex(arr, predicate) { const NOT_FOUND_INDEX = -1; return arr.reduce((acc, val, idx) => { if (acc === NOT_FOUND_INDEX) { return predicate(val, idx, arr) ? idx : NOT_FOUND_INDEX; } return acc; }, NOT_FOUND_INDEX)}

測試

findIndex([5, 12, 8, 130, 44], (element) => element > 8) // 3pipe

一、實現以下函數

/** * Return a function to make the input value processed by the provided functions in sequence from left the right. * @param {(funcs: any[]) => any} funcs * @returns {(arg: any) => any} */function pipe(...funcs) {}

使得

pipe(val => val * 2, Math.sqrt, val => val + 10)(2) // 12

利用該函數可以實現一些比較復雜的處理過程

// 挑選出 val 是正數的項對其 val 乘以 0.1 系數,然后將所有項的 val 相加,最終得到 3const process = pipe( arr => arr.filter(({ val }) => val > 0), arr => arr.map(item => ({ ...item, val: item.val * 0.1 })), arr => arr.reduce((acc, { val }) => acc + val, 0));process([{ val: -10 }, { val: 20 }, { val: -0.1 }, { val: 10 }]) // 3

二、實現以下函數,既能實現上述 pipe 的功能,而且返回函數接納參數個數可不定

/** * Return a function to make the input values processed by the provided functions in sequence from left the right. * @param {(funcs: any[]) => any} funcs * @returns {(args: any[]) => any} */function pipe(...funcs) {}

使得以下單測通過

pipe(sum, Math.sqrt, val => val + 10)(0.1, 0.2, 0.7, 3) // 12

其中 sum 已實現

/** * Sum up the numbers. * @param args number[] * @returns {number} the total sum. */function sum(...args) { return args.reduce((a, b) => a + b);}參考答案一、返回函數接受一個參數

省略過濾掉非函數的 func 步驟

/** * Return a function to make the input value processed by the provided functions in sequence from left the right. * @param {(arg: any) => any} funcs * @returns {(arg: any) => any} */function pipe(...funcs) { return (arg) => { return funcs.reduce( (acc, func) => func(acc), arg ) }}二、返回函數接受不定參數

同樣省略了過濾掉非函數的 func 步驟

/** * Return a function to make the input value processed by the provided functions in sequence from left the right. * @param {Array<(...args: any) => any>} funcs * @returns {(...args: any[]) => any} */function pipe(...funcs) {// const realFuncs = funcs.filter(isFunction); return (...args) => { return funcs.reduce( (acc, func, idx) => idx === 0 ? func(...acc) : func(acc), args ) }}

性能更好的寫法,避免無謂的對比,浪費 CPU

function pipe(...funcs) { return (...args) => { // 第一個已經處理,只需處理剩余的 return funcs.slice(1).reduce( (acc, func) => func(acc), // 首先將特殊情況處理掉當做 `acc` funcs[0](...args) ) }}

第二種寫法的 funcs[0](...args) 這個坑要注意,數組為空就爆炸了,因為空指針了。

實現 lodash.get

實現 get 使得以下示例返回 ’hello world’。

const obj = { a: { b: { c: ’hello world’ } } };get(obj, ’a.b.c’);

函數簽名:

/** * pluck the value by key path * @param any object * @param keyPath string 點分隔的 key 路徑 * @returns {any} 目標值 */function get(obj, keyPath) {}參考答案

/** * Pluck the value by key path. * @param any object * @param keyPath string 點分隔的 key 路徑 * @returns {any} 目標值 */function get(obj, keyPath) { if (!obj) { return undefined; } return keyPath.split(’.’).reduce((acc, key) => acc[key], obj);}實現 lodash.flattenDeep

雖然使用 concat 和擴展運算符只能夠 flatten 一層,但通過遞歸可以去做到深度 flatten。

方法一:擴展運算符

function flatDeep(arr) { return arr.reduce((acc, item) => Array.isArray(item) ? [...acc, ...flatDeep(item)] : [...acc, item], [] )}

方法二:concat

function flatDeep(arr) { return arr.reduce((acc, item) => acc.concat(Array.isArray(item) ? flatDeep(item) : item), [] )}

有趣的性能對比,擴展操作符 7 萬次 1098ms,同樣的時間 concat 只能執行 2 萬次

function flatDeep(arr) { return arr.reduce((acc, item) => Array.isArray(item) ? [...acc, ...flatDeep(item)] : [...acc, item], [] )}var arr = repeat([1, [2], [[3]], [[[4]]]], 20);console.log(arr);console.log(flatDeep(arr));console.time(’concat’)for (i = 0; i < 7 * 10000; ++i) { flatDeep(arr)}console.timeEnd(’concat’)function repeat(arr, times) { let result = []; for (i = 0; i < times; ++i) { result.push(...arr) } return result; }過濾掉對象中的空值

實現

clean({ foo: null, bar: undefined, baz: ’hello’ })// { baz: ’hello’ }

答案

/** * Filter out the `nil` (null or undefined) values. * @param {object} obj * @returns {any} * * @example clean({ foo: null, bar: undefined, baz: ’hello’ }) * * // => { baz: ’hello’ } */export function clean(obj) { if (!obj) { return obj; } return Object.keys(obj).reduce((acc, key) => { if (!isNil(obj[key])) { acc[key] = obj[key]; } return acc; }, {});}enumify

將常量對象模擬成 TS 的枚舉

實現 enumify 使得

const Direction = { UP: 0, DOWN: 1, LEFT: 2, RIGHT: 3,};const actual = enumify(Direction);const expected = { UP: 0, DOWN: 1, LEFT: 2, RIGHT: 3, 0: ’UP’, 1: ’DOWN’, 2: ’LEFT’, 3: ’RIGHT’,};deepStrictEqual(actual, expected);

答案:

/** * Generate enum from object. * @see https://www.typescriptlang.org/play?#code/KYOwrgtgBAglDeAoKUBOwAmUC8UCMANMmpgEw5SlEC+UiiAxgPYgDOTANsAHQdMDmAChjd0GAJQBuRi3ZdeA4QG08AXSmIgA * @param {object} obj * @returns {object} */export function enumify(obj) { if (!isPlainObject(obj)) { throw new TypeError(’the enumify target must be a plain object’); } return Object.keys(obj).reduce((acc, key) => { acc[key] = obj[key]; acc[obj[key]] = key; return acc; }, {});}Promise 串行執行器

利用 reduce 我們可以讓不定數量的 promises 串行執行,在實際項目中能發揮很大作用。此處不細講,請參考我的下一篇文章 JS 請求調度器。

拓展

請使用 jest 作為測試框架,給本文的所有方法書寫單測更多習題見 github.com/you-dont-ne…

以上就是JavaScript Reduce使用詳解的詳細內容,更多關于JavaScript Reduce使用的資料請關注好吧啦網其它相關文章!

標簽: JavaScript
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
亚洲在线久久| 国产精品毛片一区二区三区| 精品网站aaa| 日韩免费高清| 欧美中文字幕一区二区| 亚洲专区视频| 美女精品视频在线| 激情欧美一区二区三区| 日韩欧乱色一区二区三区在线| 国产欧美大片| 日韩精品一区二区三区免费观影 | 在线视频亚洲欧美中文| 亚洲毛片在线| 日本一二区不卡| 亚洲一区欧美激情| 国产乱论精品| 国产精品91一区二区三区| 亚洲免费一区三区| 91欧美在线| 亚洲精品美女91| 日韩中文欧美| 日韩毛片网站| 色婷婷精品视频| 欧美精品观看| japanese国产精品| 国产欧美在线| 国产视频亚洲| 日本精品黄色| 日韩精品成人在线观看| 日韩精品免费一区二区在线观看| 日本视频一区二区| 国产一区亚洲| 国产欧美日韩在线一区二区 | 日韩精品免费一区二区夜夜嗨| 毛片在线网站| 欧美亚洲色图校园春色| 欧美午夜不卡| 福利片在线一区二区| 午夜电影一区| 激情久久中文字幕| 免费看久久久| 综合一区二区三区| 成人三级高清视频在线看| 日韩精品久久久久久| 午夜久久影院| 在线精品亚洲欧美日韩国产| 国产欧美三级| 亚洲精选av| 亚洲精品电影| 色爱av综合网| 日本一二区不卡| 91精品美女| 日韩在线卡一卡二| 精品亚洲美女网站| 久久精品亚洲| 欧美久久香蕉| 亚洲久草在线| 中文在线а√天堂| 国产精品一页| 日韩精品视频一区二区三区| 亚洲一区区二区| 国产91精品对白在线播放| 成人国产精选| 你懂的亚洲视频| 国产日韩高清一区二区三区在线 | 亚洲一区导航| 99视频精品| 999久久久国产精品| 国产成人久久精品一区二区三区| 欧美日本二区| 91亚洲无吗| 午夜性色一区二区三区免费视频| 亚洲激情偷拍| 好看的亚洲午夜视频在线| 久久国产电影| 亚洲成人不卡| 欧美成人基地| 婷婷综合六月| 中文字幕在线看片| 欧美aaaaaa午夜精品| 国产日韩欧美一区| 91成人精品在线| 日本aⅴ精品一区二区三区 | 免费日韩成人| 国产极品模特精品一二| 国产精品夜夜夜| 国产欧美日韩视频在线| 欧美日韩18| 91欧美日韩在线| 日本成人在线视频网站| 四虎精品一区二区免费| 蜜臀91精品一区二区三区| 亚洲综合二区| 亚洲免费毛片| **爰片久久毛片| 国产精品成人自拍| 久久麻豆视频| 国产h片在线观看| 日韩欧美网址| 久久久噜噜噜| 午夜电影亚洲| 免费在线观看精品| 日韩在线观看一区二区三区| 欧美私人啪啪vps| 国产精品久久777777毛茸茸| 久久福利在线| 久久精品系列| 亚洲成人不卡| 国产亚洲精品自拍| 亚洲精品福利| 久久精品99国产精品| 免费在线观看一区| 9999国产精品| 91精品观看| 日av在线不卡| 国产免费播放一区二区| 精品亚洲成人| 麻豆精品蜜桃| 国产一级久久| 7777精品| 91一区二区三区四区| 日本久久成人网| 亚洲女人av| 国产欧美亚洲一区| 日韩在线观看一区| 国产精品三上| 欧美日韩一区二区国产| 国产成人调教视频在线观看| 久久精品卡一| 亚洲精品日本| 精品一区二区三区中文字幕视频 | 久久国产精品免费一区二区三区| 美女精品久久| 亚洲高清毛片| 亚洲精品伊人| 日韩av在线中文字幕| 99riav国产精品| 国产三级精品三级在线观看国产| 国产精品99视频| 亚洲欧美日韩国产一区| 国产精品极品国产中出| 99精品视频在线| 日本三级亚洲精品| 欧洲一区二区三区精品| 在线精品观看| av资源新版天堂在线| 亚洲在线网站| 国产极品嫩模在线观看91精品| 久久久精品网| 人人爱人人干婷婷丁香亚洲| 在线看片国产福利你懂的| 午夜一级久久| 精品一区二区男人吃奶 | 一区二区91| 欧美一级鲁丝片| 最新亚洲国产| 国产欧洲在线| 深夜福利一区| 日韩不卡在线| 国产视频网站一区二区三区| 亚洲天堂黄色| 久久国产尿小便嘘嘘| 99久久夜色精品国产亚洲1000部| 日韩二区三区四区| 欧美日韩亚洲在线观看| 国产剧情一区| 日韩午夜av在线| 国产成年精品| 视频国产精品| 激情综合网五月| 精品网站aaa| 日韩有吗在线观看| 婷婷成人在线| 久久天堂影院| 日韩精彩视频在线观看| 蜜臀av免费一区二区三区| 国产精品欧美大片| 蘑菇福利视频一区播放| 青青青免费在线视频| 久久激五月天综合精品| 伊人久久亚洲热| 天堂av在线| 国产精品v日韩精品v欧美精品网站 | 午夜电影一区| 午夜日韩在线| 免费看av不卡| 国产激情精品一区二区三区| 日韩午夜电影| 日韩不卡在线| 国产一区二区久久久久| 欧美亚洲tv| 亚洲欧美网站| 99久精品视频在线观看视频| 久久久精品区| 国产精品一区二区美女视频免费看| 亚洲伊人精品酒店| 在线精品视频在线观看高清| 日韩中文首页| 激情黄产视频在线免费观看| 久久午夜影院|