javaScript之数组中reduce的详细介绍及使用

一、reduce功能介绍及定义(自我理解)

  1. reduce方法为数组中的一个高阶函数,接受两个参数,第一个参数为回调函数,第二个为初始值。如果不给入初始值则会以数组第一项为初始值!
  2. reduce会循环数组每一项,并且会保留上一次循环的结果供下一次循环使用,最终结果为数组循环完毕后的最终返回(return)的值。
  3. 那这样咱们就可以这么理解了,给入一个初始值,后续操作都在给这个初始值做修饰!比如说给入对象最终返回对象、给入数组最终返回数组、给入字符串最终返回字符串、给入Boolean值最终返回Boolean值(true | false)…
  4. 再然后我们捋捋装饰器模式:允许向现有的对象添加功能,且不能影响它的构成(比如说一个人,你可以给他添加英语能力、可以给他添加法语能力,但是你不能让这个人的手没了),这么一看reduce不就是非常适合循环给对象添加功能吗?这不就是满足了装饰器模式了嘛。

二、各种使用方式

  1. 全网都有的最简单例子:累加递增
const arr = [1, 2, 3, 4, 5, 99]
arr.reduce((pre, next) => pre + next) // 114
  1. 【模仿数组includes】简单的includes功能模仿实现(返回某值是否在数组中出现过)
        const fn = () => { console.log(11) }
        const obj = {}
        const arr = [2, '2', fn, obj]
        const selfIncludes = (arr, value) => {
            // 使用try catche的原因是快速跳出循环。
            try {
                return arr.reduce((pre, next) => {
                    if (next === value) throw true
                    return false
                }, false)
            } catch (end) {
                if (typeof end === 'boolean') return true;
            }
        }
  1. 【模仿数组indexOf】简单的indexOf功能模仿实现(返回最先找到值的索引,没找到则返回-1)
        const fn = () => { console.log(11) }
        const obj = {}
        const arr = [2, '2', fn, obj]
        const selfIndexOf = (arr, value) => {
            // 使用try catche的原因是快速跳出循环。
            try {
                return arr.reduce((pre, next) => {
                    if (next === value) throw pre
                    return ++pre
                }, 0) && -1
            } catch (end) {
                if (typeof end === 'number') return end;
            }
        }
        console.log(selfIndexOf(arr, fn))
  1. 【模仿数组map】简单的map功能模仿实现(循环遍历数组最终返回处理后的值)
        const fn = () => { console.log(11) }
        const obj = {}
        const arr = [2, '2', fn, obj]
        const selfMap = (arr, fn) => {
            return arr.reduce((pre, next) => {
                // map方法并没有这一步
                // pre.push(fn?.(next, pre.length) || next)
                pre.push(fn(next, pre.length))
                return pre 
            }, [])
        }
        console.log(selfMap(arr, (item, i) => {
            return {
                name: item,
                index: i
            }
        }))
        console.log(selfMap(arr, () => {}))
        console.log(arr.map(() => {}))

在这里插入图片描述

  1. 【模仿数组flat】简单的flat方法模拟实现(给数组内部子集合进行将为)(递归)
	const selfFlat = (arr, deep) => {
	  if (deep > 0)
	    return arr.reduce((pre, cur) => pre.concat(Array.isArray(cur) ? flat(cur, deep - 1) : cur), [])
	  return arr.slice()
	}
调用:selfFlat([1, [2], [[3], [4]], [[[5], [6]]]], 2)
结果:(6) [1, 2, 3, 4, Array(1), Array(1)]

调用:selfFlat([1, [2], [[3], [4]], [[[5], [6]]]], 3)
结果:(6) [1, 2, 3, 4, 5, 6]

调用:selfFlat([1, [2], [[3], [4]], [[[5], [6]]]], Infinity)
结果:(6) [1, 2, 3, 4, 5, 6]
  1. 过滤掉对象中为undefined、null、空字符串、NaN的key与值
    const filterParam = (obj) => Object.entries(obj).reduce((pre, [key, value]) => {
      // 这里添加你需要做的判断依据
      if (value || value === 0) pre[key] = value
      return pre
    }, {});
    console.log(filterParam({name: undefined, age: 0, class: 'ant-design', test: NaN}))
    // {age: 0, class: 'ant-design'}
  1. lodash 中 keyBy 功能简单实现(具体细节不考虑)(使用数组内部每项的某个key对应的值为最终生成对象的key,数组当前项为最终生成对象的值)
	const arr =  [
		{
			name: '张三',
			age: 16
		},
		{
			name: '李四',
			age: 17
		},
		{
			name: '王五',
			age: 18
		},
	]
	const keyBy = (array, key) => {
		return array.reduce((pre, next) => {
			pre[next[key]] = next;
			return pre;
		}, {})
	}
	console.log(
		keyBy(arr, 'name')
	)

在这里插入图片描述

  1. 装饰器模式演示(创建Person这个类,添加一个zs的Person,把skillArr中的技能教给zs,最后让zs使用学习到的技能)
        class Person {
            // 技能对象
            skill = {
                中文: (string) => {
                    // ..... 此处经过一系列的翻译(比如说调用百度的翻译)
                    return string;
                }
            }
            constructor(params) {
                // 初始化信息
                this.info = params;
            }
            // 学习技能的功能函数
            studySkill(skillName, skillFn) {
                if (this.skill[skillName]) return '这个技能我会!';
                this.skill[skillName] = skillFn;
                return `${skillName}学习完成`;
            }
            // 说话的功能函数
            say(string, way) {
                if (!this.info.isLanguage?.includes(way)) return '你确定这是一门语言吗?';
                if (!this.skill[way]) return '我不会这个语言!';
                return this.skill[way](string);
            }
        };
        const zs = new Person({
            name: 'zs',
            age: 18,
            isLanguage: ['中文', '英语', '法语', '俄语']
        });
        // 可学习的语言技能数组
        const skillArr = {
            英语: (string) => {
                // ..... 此处经过一系列的翻译(比如说调用百度的翻译)
                const end = 'Hello world';
                return end;
            },
            法语: (string) => {
                // ..... 此处经过一系列的翻译(比如说调用百度的翻译)
                const end = 'Bonjour, le monde.';
                return end;
            },
            中文: (string) => {
                // ..... 此处经过一系列的翻译(比如说调用百度的翻译)
                const end = '你好,世界。';
                return end;
            }
        }
        // reduce 主题
        Object.entries(skillArr).reduce((pre, next) => {
            const [skillName, skillFn] = next;
            const sayMessage = pre.studySkill(skillName, skillFn);
            console.log(sayMessage);
            return pre;
        }, zs);
        // --------------
        console.log(zs);
        console.log(zs.say('你好', '英语')) // Hello world
        console.log(zs.say('你好', '法语')) // Bonjour, le monde.
        console.log(zs.say('你好', '中文')) // 你好
        console.log(zs.say('你好', '俄语')) // 我不会这个语言!
        console.log(zs.say('你好', '鸟语')) // 你确定这是一门语言吗?

在这里插入图片描述

总结

  1. reduce是真的强大,数组内部的方法应该都可以用 reduce 去实现,有兴趣的小伙伴可以去试试看。
  2. reduce是从左往右循环执行,还有一个 reduceRight 是从右往左循环执行!
  3. reduce的返回值取决于设置的初始值(常规用法),但是这也不是绝对的(非常规用法)!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值