• JS


    在前后端数据交互的过程中,为了能够减少ajax请求次数,减轻带宽压力,后端往往会将当前接口所需的参数以对象的形式集体返回。这样就导致一个问题:对象内字段属性过多,而有些小组件功能又压根不需要这么一个大对象参数(主要是对象属性过多,难得理,也懒得找),这时就需要对这个大对象做再加工处理。

    比如:将小组件所需的字段属性拎出来单独再封装成一个小对象。一般情况下我的写法是:

    let retData = {a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, j: 9, k: 10, m: 11, n: 12};
    let tempData = {
        a: retData.a,
        c: retData.c,
        d: retData.d,
        g: retData.g,
    };

    但是这种写法却很麻烦,要一个属性一个属性的添加,于是就突发奇想地想优化一下这种写法。苦思冥想该怎么玩,即要写起来简单,又要显得 big 高,所以就用到了reduce()方法。

    function handlingObjectProperty(propertyList, obj) {
        return propertyList.reduce((iter, val) => {
            if (val in obj) {
                iter[val] = obj[val];
            }
            return iter;
        }, {});
    }
    
    let retData = {a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, j: 9, k: 10, m: 11, n: 12};
    let tempData = handlingObjectProperty(['a', 'c', 'f', 'k'], retData);

    ,同样得将所需的字段属性拎出来封装成一个小对象,这样就不需要一个属性一个属性地添加了,方便了很多,一行代码就搞定。

    reduce方法的定义和用法

    reduce() 方法接收一个回调函数作为处理器,数组中的每一个元素(从左到右)【不包括数组中被删除或从未被赋值的元素】依次执行该回调函数,并最终计算为一个值或一个对象。reduce() 可以作为一个高阶函数,用于函数的 compose。

    reduce() 方法回调函数接受四个参数:提供的初始值(或上一次调用回调函数返回的值),当前被处理的元素,当前正被处理元素在数组中的索引,调用 reduce方法 的数组。

    语法:

    array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
    //
    array.reduce(callback,[initialValue])

    参数:

    initialValue参数解析

      1、不传 initialValue参数

    let testArr = [1, 2, 3, 4];
    let sum = testArr.reduce((prev, currentValue, currentIndex, testArr) => {
        console.log(prev, currentValue, currentIndex);
        return prev + currentValue;
    });
    console.log(`sum: ${sum}`);

     输出结果。

      从控制台打印结果可以看出:由于没有给 reduce方法传入 initialValue参数,所以 reduce方法的回调函数 total参数 以 testArr数组的第一个元素作为初始值,currentValue则从第二个元素开始,因而 currentIndex从1开始。所以,虽然 testArr数组的长度是4,但是 reduce方法只循环了 3次。

      2、传入 initialValue参数

    let testArr = [1, 2, 3, 4];
    let sum = testArr.reduce((prev, currentValue, currentIndex, testArr) => {
        console.log(prev, currentValue, currentIndex);
        return prev + currentValue;
    }, 0);
    console.log(`sum: ${sum}`);

    输出结果。

      这次给 reduce方法 传入了 initialValue参数,所以 total参数以 initialValue参数 作为初始值,currentValue则自然而然从第一个元素开始,currentIndex也就从0开始。所以,testArr数组的长度是4,reduce方法也就循环了 4次。

      3、如果array数组是个空数组,且未传入 initialValue参数。此时代码执行会报错,回调函数也不会被执行。

    let testArr = [];
    let sum = testArr.reduce((prev, currentValue, currentIndex, testArr) => {
        console.log(prev, currentValue, currentIndex);
        return prev + currentValue;
    });
    // index_reduce.js:18 Uncaught TypeError: Reduce of empty array with no initial value

      4、如果array数组是个空数组,但传入 initialValue参数。此时代码能顺利执行,回调函数也会执行,只是由于是空数组,没得结果而已。

    let testArr = [];
    let sum = testArr.reduce((prev, currentValue, currentIndex, testArr) => {
        console.log(prev, currentValue, currentIndex);
        return prev + currentValue;
    }, 0);

      所以:不管什么情况下,传入 initialValue参数值,都会让代码执行更安全,也更好维护。

    基本用法:

      reduce()方法的基本用法就是把回调函数做计算器使用,对数组或数列进行求和、求积。

    let testArr = [1, 2, 3, 4];
    let sum = testArr.reduce((prev, cur) => {
        return prev + cur
    }, 0);
    console.log(`sum: ${sum}`);                            // 10
    
    let pro = testArr.reduce((prev, cur) => {
        return prev * cur
    }, 1);                                                 // 求积时,initialValue不能初始化为0
    console.log(`pro: ${pro}`);                          // 24

    其他用法:

      1、计数数组中每个元素、字符串中每个字符出现的总次数

    // 获取数组内、字符串内某个元素、字符出现总次数
    function getFrequency(parList) {
        return parList.reduce((pre, cur) => {
            if (cur in pre) {
                pre[cur]++
            } else {
                pre[cur] = 1
            }
            return pre
        }, {});
    }
    
    let iterators = ['reduce', 'map', 'for', 'forOf', 'forEach', 'reduce', 'for'];
    let testStr = 'reducemapforforOfforEachreducefor';
    console.log(getFrequency(iterators));                      // {reduce: 2, map: 1, for: 2, forOf: 1, forEach: 1}
    console.log(getFrequency(testStr.split('')));              // {r: 6, e: 4, d: 2, u: 2, c: 3, …}    注:字符串不能直接被reduce,所以先把字符串分割成字符数组

      2、数组,字符串字符去重

    // 数组去重、字符串内字符去重
    function deduplication(parList) {
        return parList.reduce((pre, cur) => {
            if(!pre.includes(cur)){
                return pre.concat(cur)
            }else{
                return pre
            }
        }, []);
    }
    
    let iterators = ['reduce', 'map', 'for', 'forOf', 'forEach', 'reduce', 'for'];
    let testStr = 'reducemapforforOfforEachreducefor';
    console.log(deduplication(iterators));                     // ["reduce", "map", "for", "forOf", "forEach"]
    console.log(deduplication(testStr.split('')).join(''));    // reducmapfoOEh    注:字符串不能直接被reduce,故先将字符串分割成字符数组,reduce完成后,再格式化成字符串

      3、数组降维(又名:数组的扁平化)

    // 下面 reduce回调函数内对 pre参数的操作,只能用concat方法不能用push方法。因为,push方法虽然也将 cur添加到了 pre末尾,但是返回的却是 pre当前的长度,而不是当前 pre的
    function dimensionalityReduction(parList) {
        return parList.reduce((pre, cur) => {
            return pre.concat(Array.isArray(cur) ? dimensionalityReduction(cur) : cur)
        }, []);
    }
    
    let testArr = [[1, 2], [3, [4]], [[5], 6]];
    console.log(dimensionalityReduction(testArr));             // [1, 2, 3, 4, 5, 6]

      4、根据需求对 对象属性的操作

      41:如本文开头所述的,从一个大对象内将所需的字段属性拎出来单独再封装成一个小对象;42:对 对象数组(后端返回的表格数据,一般都是对象数组) 内各个对象特定属性值进行特定处理:如根据状态值不同显示不同提示语、数据格式转换、数据逻辑处理等。

    // 42、数据逻辑处理
    function processData(parList, attr) {
        return parList.reduce((pre, cur) => {
            return pre + cur[attr];
        }, 0);
    }
    
    let testArr = [
        {month: 1, sales: 85},
        {month: 2, sales: 30},
        {month: 3, sales: 40},
    ];
    console.log(`2020年第一季度销售总额: ${processData(testArr, 'sales')}万元`);        // 2020年第一季度销售总额: 155万元

      对于对象数组而言,reduce方法适用于 将每个对象元素内指定字段属性单独拿出来做处理,然后返回一个值或一个对象,如本文开头的字段属性重新封装,这里的数据累加等。而不是对这个数组本身的处理,对于这些对象数组本身的处理,for,forEach,map等方法更实用。

    最后

      reduce方法可以实现的东西,很多时候for循环,forEach方法、甚至map方法都可以实现,那为啥要用reduce呢。个人觉得吧,这个无关啥逼格什么的,仅仅只是想让代码更简洁,功能逻辑简单化,同时也让代码多元化,不让之前学过的东西束之高阁,喂灰尘罢了。

  • 相关阅读:
    C/C++学习的50个经典网站
    C++ 调用C++写的函数库的2种方法之一(显式调用)
    C++ 调用C++写的类库的2种方法之一(隐式链接)
    几个第三方yum源
    网站运维管理工具
    网站架构文章收集
    linux setup 相关text mode图形配置工具的安装
    nfs 安装配置
    centos6.4 minimal 安装kvm
    keepalived
  • 原文地址:https://www.cnblogs.com/donghuang/p/12942849.html
Copyright © 2020-2023  润新知