• JavaScript学习笔记:数组reduce()和reduceRight()方法


    很多时候需要累加数组项的得到一个值(比如说求和)。如果你碰到一个类似的问题,你想到的方法是什么呢?会不会和我一样,想到的就是使用forwhile循环,对数组进行迭代,依次将他们的值加起来。比如:

    var arr = [1,2,3,4,5,6];
    Array.prototype.sum = function (){
        var sumResult = 0;
        for (var i = 0; i < this.length; i++) {
            sumResult += parseInt(this[i]);
        }
        return sumResult;
    }
    
    arr.sum(); // 21
    

    或者

    var arr =  [1,2,3,4,5,6];
    
    Array.prototype.sum = function () {
        var sumResult = 0;
        var i = this.length;
        while (i--) {
            sumResult += parseInt(this[i]);
        }
        return sumResult;
    }
    
    arr.sum(); // 21
    

    那他们是不是最好的方案呢?先来看看他们所耗时间。

    // 测试for和while循环实现数组求和的性能
    
    var arr = [1,2,3,4,5,6];
    
    // for循环
    console.time("forLoop");
    
    Array.prototype.forLoop = function (){
        for (var i = 0; i < 10000; i++) {
            var sumResult = 0;
            for (var j = 0; j < this.length; j++) {
                sumResult += parseInt(this[j]);
            }
        }
        return sumResult;
    }
    arr.forLoop();
    console.log('最终的值:' + arr.forLoop()); // 21
    console.timeEnd("forLoop"); // 54.965ms
    

    再来看看while循环所用时间:

    var arry = [1,2,3,4,5,6];
    
    console.time("whileLoop");
    
    Array.prototype.whileLoop = function () {
    
        for (var i = 0; i < 10000; i++) {
            var sumResult = 0;
            for (var j = 0; j < this.length; j++) {
                sumResult += parseInt(this[j]);
            }
        }
        return sumResult;
    }
    
    arry.whileLoop();
    console.log('最终的值:' + arry.whileLoop()); // 21
    console.timeEnd("whileLoop"); // 53.056ms
    

    看看对比结果

    循环类型最终值(和)所费时间
    for 21 54.965ms
    while 21 53.056ms

    备注:数组[1,2,3,4,5,6]做了10000次循环的累加。

    虽然上面使用forwhile都能实现需要的效果,但在JavaScript中有没有更好的方案呢?回答是肯定的,在JavaScript中(ESMAScript 5)提供了另外两个数组的方法reduce()reduceRight(),这两个数组会迭代数组的所有数组项,然后返回一个最终值。接下来的内容,主要来学习这两种方法。

    reduce()方法

    reduce()方法接收一个函数callbackfn作为累加器(accumulator),数组中的每个值(从左到右)开始合并,最终为一个值。

    语法

    array.reduce(callbackfn,[initialValue])
    

    reduce()方法接收callbackfn函数,而这个函数包含四个参数:

    function callbackfn(preValue,curValue,index,array){}
    
    • preValue: 上一次调用回调返回的值,或者是提供的初始值(initialValue)
    • curValue: 数组中当前被处理的数组项
    • index: 当前数组项在数组中的索引值
    • array: 调用 reduce()方法的数组

    initialValue作为第一次调用 callbackfn函数的第一个参数。

    reduce()方法为数组中的每一个元素依次执行回调函数callbackfn,不包括数组中被删除或从未被赋值的元素,接受四个参数:初始值(或者上一次回调函数的返回值),当前元素值,当前索引,调用 reduce() 的数组。

    回调函数第一次执行时,preValue 和 curValue 可以是一个值,如果 initialValue 在调用 reduce() 时被提供,那么第一个 preValue 等于 initialValue ,并且curValue 等于数组中的第一个值;如果initialValue 未被提供,那么preValue 等于数组中的第一个值,`curValue等于数组中的第二个值。

    来看一个示例:

    var arr = [0,1,2,3,4];
    
    arr.reduce(function (preValue,curValue,index,array) {
        return preValue + curValue;
    }); // 10
    

    示例中的回调函数被执行四次,每次参数和返回的值如下:

     preValuecurValueindexarray返回值
    第一次回调 0 1 1 [0,1,2,3,4] 1
    第二次回调 1 2 2 [0,1,2,3,4] 3
    第三次回调 3 3 3 [0,1,2,3,4] 6
    第四次回调 6 4 4 [0,1,2,3,4] 10

    上面的示例reduce()方法没有提供initialValue初始值,接下来再上面的示例中,稍作修改,提供一个初始值,这个值为5。这个时候reduce()方法会执行五次回调,每次参数和返回的值如下:

    var arr = [0,1,2,3,4];
    
    arr.reduce(function (preValue,curValue,index,array) {
        return preValue + curValue;
    }, 5); //15
    
     preValuecurValueindexarray返回值
    第一次回调 5 0 0 [0,1,2,3,4] 5
    第二次回调 5 1 1 [0,1,2,3,4] 6
    第三次回调 6 2 2 [0,1,2,3,4] 8
    第四次回调 8 3 3 [0,1,2,3,4] 11
    第五次回调 11 4 4 [0,1,2,3,4] 15

    这样一来,不用多说,应该都知道,可以使用reduce()实现数组求和的功能。如:

    var arr = [1,2,3,4,5,6];
    
    Array.prototype.sum = function (){
        var sumResult = 0;
        return this.reduce(function (preValue, curValue) {
            return sumResult = preValue + curValue;
        });
        return sumResult;
    }
    arr.sum(); // 21
    

    回到文章的前面,来看看使用reduce()方法对数组求和,需要多少时间:

    var arr = [1,2,3,4,5,6];
    
    console.time("ruduce");
    Array.prototype.ruduceSum = function (){
        for (var i = 0; i < 10000; i++) {
            return  this.reduce (function (preValue, curValue) {
                return preValue + curValue;
            });
        }
    }
    arr.ruduceSum();
    console.log('最终的值:' + arr.ruduceSum()); // 21
    console.timeEnd("ruduce"); // 0.417ms
    

    同时看看所费时间的对比:

    循环类型最终值(和)所费时间
    for 21 54.965ms
    while 21 53.056ms
    reduce 21 0.417ms

    在Chrome浏览器下,每次执行的数据都会略有不同,但可以明显的看出reduce()对数组项求和所费时间是最短的。

    reduceRight()方法

    reduceRight()方法的功能和reduce()功能是一样的,不同的是reduceRight()从数组的末尾向前将数组中的数组项做累加。

    reduceRight()首次调用回调函数callbackfn时,prevValue 和 curValue 可以是两个值之一。如果调用 reduceRight() 时提供了 initialValue 参数,则 prevValue 等于 initialValuecurValue 等于数组中的最后一个值。如果没有提供 initialValue 参数,则 prevValue 等于数组最后一个值, curValue 等于数组中倒数第二个值。

    来看实例:

    var arr = [0,1,2,3,4];
    
    arr.reduceRight(function (preValue,curValue,index,array) {
        return preValue + curValue;
    }); // 10
    

    回调将会被调用四次,每次调用的参数及返回值如下:

     preValuecurValueindexarray返回值
    第一次回调 4 3 3 [0,1,2,3,4] 7
    第二次回调 7 2 2 [0,1,2,3,4] 9
    第三次回调 9 1 1 [0,1,2,3,4] 10
    第四次回调 10 0 0 [0,1,2,3,4] 10

    如果提供一个初始值initialValue5:

    var arr = [0,1,2,3,4];
    
    arr.reduceRight(function (preValue,curValue,index,array) {
        return preValue + curValue;
    }, 5); // 15
    

    回调将会被调用五次,每次调用的参数及返回的值如下:

     preValuecurValueindexarray返回值
    第一次回调 5 4 4 [0,1,2,3,4] 9
    第二次回调 9 3 3 [0,1,2,3,4] 12
    第三次回调 12 2 2 [0,1,2,3,4] 14
    第四次回调 14 1 1 [0,1,2,3,4] 15
    第五次回调 15 0 0 [0,1,2,3,4] 15

    同样的,可以对一个数组求和,也可以使用reduceRight()方法:

    var arr = [1,2,3,4,5,6];
    
    console.time("ruduceRight");
    Array.prototype.ruduceRightSum = function (){
        for (var i = 0; i < 10000; i++) {
            return  this.reduceRight (function (preValue, curValue) {
                return preValue + curValue;
            });
        }
    }
    arr.ruduceRightSum();
    console.log('最终的值:' + arr.ruduceSum()); // 21
    console.timeEnd("ruduceRight"); // 5.725ms
    

    总结

    reduce()reduceRight()两个方法功能都是类似的,可以让数组调用一个回调函数callbackfn作为累加器。实际上根据这个回调函数,可以实现不同的功能,比如说,对数组项求合;将多个数组合并到一个数组等等。甚至配合数组其他的方法你还可以做更多功能的处理。如果感兴趣的话不仿尝试一二。

    初学者学习笔记,如有不对,还希望高手指点。如有造成误解,还希望多多谅解。

    大漠

    常用昵称“大漠”,W3CPlus创始人,目前就职于手淘。中国Drupal社区核心成员之一。对HTML5、CSS3和Sass等前端脚本语言有非常深入的认识和丰富的实践经验,尤其专注对CSS3的研究,是国内最早研究和使用CSS3技术的一批人。CSS3、Sass和Drupal中国布道者。2014年出版《图解CSS3:核心技术与案例实战》。

    如需转载,烦请注明出处:http://www.w3cplus.com/javascript/array-part-8.html

  • 相关阅读:
    ES6 Promise 用法转载
    移动端滚动性能优化
    Python之禅
    Day01~15
    Python
    第一章 Java起源
    IMP-00009: 导出文件异常结束 imp
    浏览器访问网页的详细内部过程
    数据库连接池
    连接数据库 六大步骤
  • 原文地址:https://www.cnblogs.com/huenchao/p/6091313.html
Copyright © 2020-2023  润新知