《JS权威指南学习总结--7.9 ES5中的数组方法》

内容要点:编程

   ES5中定义了9个新的数组方法来遍历、映射、过滤、检测、简化和搜索数组。数组

   概述:首先,大多数方法的第一个参数接收一个函数,而且对数组的每一个元素(或一个元素)调用一次该函数。函数式编程

           若是是稀疏数组,对不存在的元素不调用传递的函数。函数

           在大多数状况下,调用提供的函数使用三个参数:数组元素、元素的索引和数组自己。优化

          一般,只须要第一个参数值,能够忽略后两个参数。大多数ES5数组的方法的第一个参数是一个函数,第二个参数是可选的。若是有第二个参数,则调用的函数被看作是第二个参数的方法。this

          也就是说,在调用函数时传递进去的第二个参数做为它的this关键字的值来使用。spa

          被调用的函数的返回值很是重要,可是不一样的方法处理返回值的方法也不同。ES5中的数组方法都不会修改它们调用的原始数值。对象

          固然,传递给这些方法的函数是能够修改这些数组的。索引

一.forEach()数学

      forEach()方法从头到尾遍历数组,为每一个元素调用指定的函数。

      如上所述,传递的函数做为forEach()的第一个参数。而后forEach()使用三个参数调用该函数:数组元素、元素的索引和数组自己,

      若是只关心数组元素的值,能够编写只有一个参数的函数--额外的参数将忽略:

      var data = [1,2,3,4,5];  //要求和的数组

      //计算数组元素的和值

      var sum = 0;   //初始为0

      data.forEach(function(value){ sum+=value; });  //将每一个值累加到sum上

      sum   //=>15

     //每一个数组元素的值自加1

       data.forEach(function(v,i,a){ a[i] = v + 1; })

      data             //=>[2,3,4,5,6]

      注意,forEach()没法在全部元素都传递给调用的函数以前终止遍历。

      也就是说,没有像for循环中使用的相应的break语句。若是要提早终止,必须把forEach()方法放在一个try块中,并能抛出一个异常。

      若是forEach()调用的函数抛出foreach.break异常,循环会提早终止。

             function foreach(a,f,t){

               try{ a.forEach(f,t); }

               catch(e){ if( e ===foreach.break )  return;

               else throw e;

            } 

         }

         foreach.break = new Error("StopIteration");

二.map()

   map()方法将调用的数组的每一个元素传递给指定的函数,并返回一个数组,它包含该函数的返回值。

   例如,

     a = [1,2,3];

     b = a.map(function(){ return x*x }); //b是[1,4,9]

    传递给map()的函数的调用方法给forEach()的函数的调用方式同样。但传递给map()的函数应该有返回值。注意,map()返回的是新数组:它不修改调用的数组。

    若是是稀疏数组,返回的也是相同方式的稀疏数组:它具备相同的长度,相同的缺失元素。

三.filter()

   filter()方法返回的数组元素是调用的数组的一个子集。

   传递的函数是用来逻辑判断的:该函数返回true或false。调用判断函数就像调用forEach()和map()同样。

   若是返回值为true或能转化为true的值,那么传递给断定函数的元素就是这个子集的成员,它将被添加到一个做为返回值的数组中。

   例如:

      a = [5,4,3,2,1];

      smallvalues = a.filter( function(x) { return x<3 } ); //[2,1]

      everyother = a.filter( function(x,i){ return i%2==0 } ); //[5,3,1]

     注意,filter()会跳过稀疏数组中缺乏的元素,它的返回值老是稠密的,为了压缩稀疏数组的空缺,代码以下:

           var dense = sparse.filter( function(){ return true; } );

     甚至,压缩空缺并删除undefined和null元素,能够这样使用filter():

        a = a.filter( function(x) { return x !== undefined && x!=null; } );

四.every()和some()

    every()和some()方法是数组的逻辑断定:它们对数组元素应用指定的函数进行断定,返回true或false。

    every()方法就像数学中的 "针对全部" 的量词:当且仅当针对数组中的全部元素调用判断函数都返回true,它才返回true:

    a = [1,2,3,4,5]

    a.every( function(x) { return x <10; } )  //=>true,

    a.every( function(x) { return x%2===0; } ) //=>false:不是全部的值都是偶数

    some()方法就像数学中的"存在"的量词:当数组中至少有一个元素调用断定函数返回true,它就返回true;而且当且仅当数值中的全部元素调用判断函数都返回false,它才返回false:

      a = [1,2,3,4,5];

      a.some( function(x){ return x%2===0; } ) //=>true

      a.some(isNaN)   //=>false:a不包含非数组元素

五.reduce()和reduceRight()

     reduce()和reduceRight()方法使用指定的函数将数组元素进行组合,生成单个值。这在函数式编程中是常见的操做,也能够称为"注入"和"折叠"。

     例如:

         var a = [1,2,3,4,5];

         var sum = a.reduce( function(x,y) { return x+y },0 ); //数组求和

        var  product = a.reduce( function(x,y){ return x*y },1  ); //数组求积

        var max = a.reduce( function( x,y ){ return (x>y)?x:y; } ); //求最大值

    reduce()须要两个参数。第一个是执行化简操做的函数。化简函数的任务就是用某种方法把两个值组合或化简为一个值,并返回化简后的值。

    在上述例子中,函数经过加法、乘法或取最大值的方法组合两个值。第二个(可选)参数是一个传递给函数的初始值。

     reduce()使用的函数与forEach()和map()使用的函数不一样。比较熟悉的是:

            数组元素的索引和数组自己将做为第2-4个参数传递给函数。

            第一个参数是到目前为止的化简操做积累的结果。第一次调用函数时,第一个参数就是初始值,它就是传递reduce()的第二个参数。在接下来的调用中,这个值就是上一次化简函数的返回值。

           在上面的第一个例子中,第一次调用化简函数时的参数是0和1.将二者相加并返回1.再次调用时的参数是1和2,它返回3.

           而后计算3+3=六、6+4=10,最后计算10+5=15.最后的值是15,reduce()返回这个值。

   上面第三次调用reduce()时只有一个参数:没有指定初始值。当不指定初始值调用reduce()时,它将使用数组的第一个元素做为其初始值。

   当不指定初始值调用reduce()时,它将使用数组的第一个元素做为其初始值。这意味着第一次调用化简函数就使用了第一次和第二个数组元素做为其第一个和第二个参数。在上面求和与求积德例子中,能够省略初始化参数。

    在空数组上,不带初始值参数调用reduce()将致使类型错误异常。若是调用它的时候只有一个值--数组只有一个元素而且没有指定初始值,或者有一个空数组而且指定一个初始值--reduce()只是简单地返回那个值而不会调用化简函数。

     reduceRight()的工做原理和reduce()同样,不一样的是它按照数组索引从高到低(从左到右)处理数组,而不是从低到高。

     若是化简操做的优化顺序是从右到左,你可能想使用它,例如:

     var a = [2,3,4];

     //计算2^(3^4).乘方操做的优先顺序是从右到左

     var big = a.reduceRight( function( accumulator,value ){ return Math.pow(value,accumulator); } );

     注意,reduce()和reduceRight()都能接收一个可选的参数,它指定了化简函数调用时的this关键字的值。可选的初始值参数仍然须要占一个位置。

      值得注意的是,上面描述的every()和some()方法是一种类型的数组化简操做。可是不一样的是,它们会尽早终止遍历而不老是访问每个数组元素。

      当两个对象拥有同名的属性时,union()函数使用第一个参数的属性值。这样,reduce()和reduceRight()在使用union()时给出了不一样的结果。

        var objects = [{x:1,a:1},{y:2,a:2},{z:3,a:3}];

        var leftunion = objects.reduce( union ); //{ x:1,y:2,z:3,a:1 }

       var rightunion = objects.reduceRight( union );  //{ x:1,y:2,z:3,a:3 }

六.indexOf()和lastIndexOf()  

     indexOf()和lastIndexOf()搜索整个数组具备给定值的元素,返回找到的第一个元素的索引或者若是没有找到就返回-1.indexOf()从头到尾搜索,而lastIndexOf()则反向搜索。

     a = [0,1,2,1,0];

     a.indexOf(1)  //=>:a[1]是1

     a.lastIndexOf(1) //=>3:a[3]是1

     a.indexOf(3) //=>-1:没有值为3的元素

     不一样于本节描述的其余方法,indexOf()和lastIndexOf()方法不接收一个函数做为其参数。

      第一个参数是须要搜索的值,第二个参数是可选的:它指定数组中的一个索引,从那里开始搜索。若是省略该参数,indexOf()从头开始搜索,而lastIndexOf()从末尾开始搜索。

      第二个参数也能够是负数,它表明相对数组末尾的偏移量,对于splice()方法:例如,-1指定数组的最后一个元素。

         以下函数在一个数组中搜索指定的值并返回包含全部匹配的数组索引的一个数组。

            //在数组中查找全部出现的x,并返回一个包含匹配索引的数组

            function findall(a,x){ 

                  var results = [];   //将会返回的数组

                        len = a.length, //待搜索数组的长度

                        pos = 0; //开始搜索的位置

                  while( pos < len ){

                         pos = a.indexOf(x,pos); //搜索

                         if(pos===-1) break;

                        results.push(pos);      //不然,在数组中存储索引

                        pos = pos+1;            //并从下一个位置开始搜索

                     }

               return results;                   //返回包含索引的数组

}

相关文章
相关标签/搜索