成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

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

JavaScript Reduce使用詳解

瀏覽:308日期: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
相關文章:
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
日韩福利视频网| 国产欧美大片| 99精品视频免费观看视频| 免费精品视频在线| 国产嫩草影院久久久久| 色欧美乱欧美15图片| 亚洲欧美亚洲| 老色鬼精品视频在线观看播放| 国产欧美综合在线| 欧洲精品在线观看| 欧美国产专区| 精品一区二区三区免费毛片爱| 亚洲欧洲日产国产综合网| 欧美日韩一区二区三区免费看| 国产精品av一区二区| 久久成人18免费观看| 国产精品国产三级国产aⅴ无密码 国产精品国产三级国产aⅴ原创 | 亚洲国产日韩一区二区| 日韩精品在线网站| 欧美午夜精品一区二区三区| 亚洲在线播放电影| 国产精品二区二区三区| 成人美女视频在线看| 五月婷婷综合激情| 国产精品伦理在线| 久久免费看少妇高潮| 4438x亚洲最大成人网| 色8久久人人97超碰香蕉987| 日韩视频不卡| 国产精品二区在线| 你懂的视频一区二区| 国产98色在线|日韩| 国产综合色视频| 日本中文在线一区| 亚洲激情在线激情| 亚洲色图一区二区| 国产精品乱子久久久久| 日韩欧美在线123| 欧美日韩一级片在线观看| 中文在线不卡| 亚洲精品视频一区二区三区 | 亚洲三级观看| 国产一区视频观看| 97久久超碰精品国产| 成人在线视频一区| 麻豆精品视频在线观看视频| 最新国产乱人伦偷精品免费网站| 亚洲尤物在线视频观看| 一本到不卡免费一区二区| 久久99精品国产麻豆婷婷洗澡| 欧美一区二区三级| av午夜精品一区二区三区| 国产剧情在线观看一区二区| 国产精品自拍一区| 国产精品影视在线观看| 国产在线播精品第三| 国产在线看一区| 国产精品一品二品| 成人国产亚洲欧美成人综合网| 国产91丝袜在线播放| 成人理论电影网| 在线观看日韩av电影| 一区二区精品在线| 久久激情综合| 欧美精品丝袜久久久中文字幕| 欧美人伦禁忌dvd放荡欲情| 3d动漫精品啪啪1区2区免费| 亚洲精品一区二区三区在线观看| 国产日韩在线不卡| 一区二区在线观看视频在线观看| 亚洲va欧美va国产va天堂影院| 久久爱另类一区二区小说| 国产麻豆成人精品| 91性感美女视频| 最新国产乱人伦偷精品免费网站| 老鸭窝亚洲一区二区三区| 欧美主播一区二区三区美女| 91麻豆精品91久久久久久清纯 | 久久日韩精品一区二区五区| 久久中文字幕电影| 亚洲影院理伦片| 国产麻豆9l精品三级站| 国内精品亚洲| 欧美精品v国产精品v日韩精品| 日本一区二区在线不卡| 一区二区三国产精华液| 国产一区二区三区在线观看精品 | 国产成a人亚洲精品| 亚洲精品一区二区三区蜜桃久| 欧洲国产伦久久久久久久| 国产日产精品1区| 免费在线观看精品| 午夜久久tv| 日本高清免费不卡视频| 国产精品天天看| 国内外成人在线| 日韩午夜免费视频| 精品福利一区二区三区免费视频| 亚洲最色的网站| 粗大黑人巨茎大战欧美成人| 午夜亚洲影视| 亚洲精品在线观看视频| 奇米888四色在线精品| 国产精品yjizz| 欧美一区二区三区视频在线 | 国产激情偷乱视频一区二区三区| 99视频日韩| 久久久久9999亚洲精品| 免费看黄色91| 一区二区激情| 久久久久久久网| 日韩国产欧美在线视频| 欧美日韩亚洲一区二区三区四区| 欧美性生活久久| 亚洲激情男女视频| 91丨国产丨九色丨pron| 男人的天堂亚洲在线| 国产精品视频yy9299一区| 国产黄色成人av| 欧美图片一区二区三区| 亚洲成a人在线观看| 亚洲国产精品www| 国产女主播一区| 国产精品一区二区在线播放| 在线视频一区二区免费| 亚洲综合色视频| 欧美日韩高清在线一区| 欧美第一区第二区| 国产在线精品一区二区三区不卡| 亚洲主播在线| 国产精品护士白丝一区av| 91美女在线观看| 精品国产免费一区二区三区香蕉| 国产盗摄女厕一区二区三区| 欧美日免费三级在线| 免费成人在线影院| 久久久久九九九| 日韩精品久久理论片| 蘑菇福利视频一区播放| 天堂在线一区二区| 久久精品男女| 亚洲一区二区三区国产| 国产精品毛片在线| 亚洲男人都懂的| 国产日韩精品久久| 一区二区三区中文字幕在线观看| 亚洲精选在线| 亚洲超丰满肉感bbw| 久久综合影音| 久久精品国产免费看久久精品| 久久综合九色| 麻豆精品一区二区三区| 69堂成人精品免费视频| 国产成人av电影在线| 久久新电视剧免费观看| 欧美日韩亚洲一区在线观看| 日本一区二区三区在线观看| 国模 一区 二区 三区| 18成人在线观看| 国产精品手机视频| 日本不卡不码高清免费观看| 欧美色欧美亚洲另类二区| 国产在线视视频有精品| 欧美成人性战久久| 91免费版在线| 一区二区三区在线看| 色婷婷亚洲综合| 国产精品中文字幕一区二区三区| 精品国产三级电影在线观看| 亚洲私拍自拍| 免费欧美在线视频| 日韩一区和二区| 日韩二区三区在线观看| 久久女同互慰一区二区三区| 精品剧情v国产在线观看在线| 日韩一区二区在线观看视频 | 精品中文字幕一区二区| 亚洲免费在线观看视频| 久久久久久国产精品mv| 日本不卡免费在线视频| 亚洲欧洲精品天堂一级| 亚洲少妇最新在线视频| 亚洲特级片在线| 亚洲欧洲精品成人久久奇米网| 成人国产亚洲欧美成人综合网| 国产精品热久久久久夜色精品三区 | 欧美大度的电影原声| 日韩一区二区三区免费看 | 亚洲综合国产| 国产一区二区电影| 亚洲三级免费观看| 在线播放中文一区| 亚洲视频观看| 国产在线一区二区综合免费视频| 久久精品在线观看| 亚洲美女网站| 成人一区在线观看| 亚洲电影视频在线| 久久先锋影音av| 欧美三级韩国三级日本三斤|