电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

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

JavaScript Reduce使用詳解

瀏覽:123日期: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
相關文章:
主站蜘蛛池模板: 江西高职单独招生-江西单招考试-江西高职单招网 | 流程管理|流程管理软件|企业流程管理|微宏科技-AlphaFlow_流程管理系统软件服务商 | 生产自动包装秤_颗粒包装秤_肥料包装秤等包装机械-郑州鑫晟重工科技有限公司 | 运动木地板_体育木地板_篮球馆木地板_舞台木地板-实木运动地板厂家 | 西宁装修_西宁装修公司-西宁业之峰装饰-青海业之峰墅级装饰设计公司【官网】 | Maneurop/美优乐压缩机,活塞压缩机,型号规格,技术参数,尺寸图片,价格经销商 | 常州律师事务所_常州律所_常州律师-江苏乐天律师事务所 | 冷水机-工业冷水机-冷水机组-欧科隆品牌保障 | 深圳激光打标机_激光打标机_激光焊接机_激光切割机_同体激光打标机-深圳市创想激光科技有限公司 深圳快餐店设计-餐饮设计公司-餐饮空间品牌全案设计-深圳市勤蜂装饰工程 | 施工围挡-施工PVC围挡-工程围挡-深圳市旭东钢构技术开发有限公司 | 钢绞线万能材料试验机-全自动恒应力两用机-混凝土恒应力压力试验机-北京科达京威科技发展有限公司 | 两头忙,井下装载机,伸缩臂装载机,30装载机/铲车,50装载机/铲车厂家_价格-莱州巨浪机械有限公司 | 上海冠顶工业设备有限公司-隧道炉,烘箱,UV固化机,涂装设备,高温炉,工业机器人生产厂家 | 除甲醛公司-甲醛检测治理-杭州创绿家环保科技有限公司-室内空气净化十大品牌 | 南京泽朗生物科技有限公司-液体饮料代加工_果汁饮料代加工_固体饮料代加工 | 全国国际化学校_国际高中招生_一站式升学择校服务-国际学校网 | 北京京云律师事务所| 金刚网,金刚网窗纱,不锈钢网,金刚网厂家- 河北萨邦丝网制品有限公司 | 澳门精准正版免费大全,2025新澳门全年免费,新澳天天开奖免费资料大全最新,新澳2025今晚开奖资料,新澳马今天最快最新图库 | 长沙发电机-湖南发电机-柴油发电机供应厂家-长沙明邦智能科技 | 带式压滤机_污泥压滤机_污泥脱水机_带式过滤机_带式压滤机厂家-河南恒磊环保设备有限公司 | 奥运星-汽车性能网评-提供个性化汽车资讯| 河南砖机首页-全自动液压免烧砖机,小型砌块水泥砖机厂家[十年老厂] | 吸音板,隔音板,吸音材料,吸音板价格,声学材料 - 佛山诺声吸音板厂家 | 中国品牌排名投票_十大品牌榜单_中国著名品牌【中国品牌榜】 | 铝合金风口-玻璃钢轴流风机-玻璃钢屋顶风机-德州东润空调设备有限公司 | 盘式曝气器-微孔曝气器-管式曝气器-曝气盘-斜管填料 | 郑州市前程水处理有限公司 | 新疆系统集成_新疆系统集成公司_系统集成项目-新疆利成科技 | 温控器生产厂家-提供温度开关/热保护器定制与批发-惠州市华恺威电子科技有限公司 | 营养师网,营养师考试时间,报名入口—网站首页 | 船老大板材_浙江船老大全屋定制_船老大官网| 档案密集架,移动密集架,手摇式密集架,吉林档案密集架-厂家直销★价格公道★质量保证 | 北京企业宣传片拍摄_公司宣传片制作-广告短视频制作_北京宣传片拍摄公司 | 成都顶呱呱信息技术有限公司-贷款_个人贷款_银行贷款在线申请 - 成都贷款公司 | 气力输送_输送机械_自动化配料系统_负压吸送_制造主力军江苏高达智能装备有限公司! | 槽钢冲孔机,槽钢三面冲,带钢冲孔机-山东兴田阳光智能装备股份有限公司 | 山东螺杆空压机,烟台空压机,烟台开山空压机-烟台开山机电设备有限公司 | 山东螺杆空压机,烟台空压机,烟台开山空压机-烟台开山机电设备有限公司 | ph计,实验室ph计,台式ph计,实验室酸度计,台式酸度计 | 精益专家 - 设备管理软件|HSE管理系统|设备管理系统|EHS安全管理系统 | 铝合金重力铸造_铝合金翻砂铸造_铝铸件厂家-东莞市铝得旺五金制品有限公司 |