ECMAScript 5中的数组方法

作者: jicemoon | 来源:发表于2016-04-12 10:01 被阅读246次

    (JavaScript权威指南 笔记)

    ECMAScript 5定义了几个新的数组方法, 根据功能可以分为

    • 遍历 - forEach;
    • 映射 - map;
    • 过滤 - filter;
    • 检测 - every和some;
    • 简化 - reduce和reduceRight;
    • 搜索 - indexOf和lastIndexOf;
    • 判断 - Array.isArray;

    下面一一介绍

    forEach - 遍历

    函数原形:

    arr.forEach(func);

    此方法会从头到尾的遍历数组, 并为每个元素调用参数中指定的函数, 没有返回值.
    参数func的原形:

    function func(value[, index[, arr]]);

    参数含义:

    • value: 数组元素值;
    • index: 元素索引;
    • arr: 当前数组本身;

    例如:

    var data = [1,2,3,4,5];
    //计算数组元素的和
    var sum = 0;
    data.forEach(function (value){ sum += value;});
    console.log("当前数组的和为: " + sum); // => 15
    //每个数组元素的值自加1
    data.forEach(function(v, i, a){ arr[i] = v + 1;});
    console.log(data); // => [2,3,4,5,6]
    

    注意: forEach会自动跳过稀疏数组中缺少的元素, 如

    var arr = [0,1];
    arr[3] = null;
    arr[4] = undefined;
    arr[5] = 9;
    function func(value,index, arr){
      console.log(index + " --> " + value);
    }
    arr.forEach(func);
    

    上例中的输出结果:

    0 --> 0
    1 --> 1
    3 --> null
    4 --> undefined
    5 --> 9

    对应js的实现函数如下(输出结果于上例相同):

    //接上例
    function myForEach(a, func){
      //for(var i = 0; i < a.length; i++){
      //  if(i in a)
      //    func(arr[i], i, a);
      //}
      //或者
      for(var i in a){
        func(arr[i], i, a);
      }
    }
    myForEach(arr, func);
    

    还有, 此方法无法在所有元素都传递给调用的函数之前终止遍历 . 也就是说, 没有像for循环中使用的相应的break语句. 如果要提前终止, 必须把forEach方法放在try块中, 并能抛出一个异常;

    map - 映射

    newArr = arr.map(func);

    将调用数组的每个元素传递给参数中指定的函数(这里是func), func的返回值将作为map返回数组对应位置的新元素;
    参数func的原形和上述forEach是一样的, 只是需要返回值:

    function func(value[, index[, arr]]);

    参数含义:

    • value: 数组元素值;
    • index: 元素索引;
    • arr: 当前数组本身;
    • 该函数必须返回一个值, 否则将没有意义;

    实例

    var arr = [1,2];
    function mapFunc(value){
      return value*value;
    }
    var b = arr.map(mapFunc);
    console.log(b); // => [ 1, 4 ]
    console.log(arr); // => [ 1, 2 ]
    

    从输出可以看出, map返回的是一个新数组, 并不修改调用的原数组, 上述实例相当于:

    //接上例
    function myMap(a, func){
      var c = [];
      for(var i = 0; i < a.length; i++){
        c[i] = func(arr[i], i, a);
      }
      return c;
    }
    console.log(myMap(arr, mapFunc));
    

    另外需要注意的是, 如果是稀疏数组, 返回的也是相同方式的稀疏数组, 具有相同的长度, 相同的确实元素;

    filter - 过滤

    arr.filter(func);

    返回的数组元素时调用数组的一个子集(包含参数func返回为true的元素), 不改变原数组,
    参数func的原形和上述forEach是一样的, 只是需要返回值:

    function func(value[, index[, arr]]);

    参数含义:

    • value: 数组元素值;
    • index: 元素索引;
    • arr: 当前数组本身;
    • 该函数返回一个布尔值, 确定filter返回数组中是否包含对应元素;

    例如

    var arr = [1,2,3,4,5];
    function mapFunc(value, index, arr){
      return value > 3;
    }
    var b = arr.filter(mapFunc)
    console.log(b); // => [4,5]
    console.log(arr); // => [1,2,3,4,5]
    

    执行结果相当于以下函数

    //接上例
    function myFilter(a, func){
      var c = [];
      for(var i = 0; i < a.length; i++){
        if(func(arr[i], i, a))
          c.push(a[i]);
      }
      return c;
    }
    console.log(myFilter(arr, mapFunc));  // => [4,5]
    

    注意: filter会跳过稀疏数组中缺少的元素, 他的返回数组总是稠密的;

    every和some - 检测

    这两个方法用来对数组中的元素应用参数中的函数进行检测

    arr.every(func);
    arr.some(func);

    参数func的原形于上述filter是一样的, 这里就不说了;
    当且仅当针对数组中的所有元素调用判定函数都返回true, every()才返回true;
    相反, 当且仅当针对数组中的所有元素调用判定函数都返回false, every()才返回false;
    实例:

    var arr = [1,2,3,4,5];
    function func1(value, index, arr){
      return value > 3;
    }
    function func2(value, index, arr){
      return value > 0;
    }
    function func3(value, index, arr){
      return value >5;
    }
    //不是所有值都大于3, 所以返回false
    console.log(arr.every(func1)); // => false
    //所有值都大于0, 所以返回true
    console.log(arr.every(func2)); // => true
    
    console.log(arr.some(func1)); // => true
    console.log(arr.some(func3)); // => false
    

    执行结果相当于以下函数

    //接上例
    //相当于arr.every
    function myEvery(a, func){
      for(var i = 0; i < a.length; i++){
        if(!func(arr[i], i, a))
          return false;
      }
      return true;
    }
    //相当于arr.some
    function mySome(a, func){
      for(var i = 0; i < a.length; i++){
        if(func(arr[i], i, a))
          return true;
      }
      return false;
    }
    console.log(myEvery(arr, func1));  // => false
    console.log(myEvery(arr, func2));  // => true
    console.log(mySome(arr, func1));  // => true
    console.log(mySome(arr, func3));  // => false
    

    注意: 这两个方法不会遍历所有元素, 一旦确认返回值, 就会停止遍历(类似于上述我写的myEvery和mySome);

    reduce和reduceRight - 简化

    arr.reduce(func[, initValue])
    arr.reduceRight(func[, initValue])

    这两个方法会使用参数中的函数将数组元素进行组合, 并返回单个元素;

    • func: 用于合并的函数;
    • initValue: 合并前的初始值, 此值会作为func第一次被调用时的第一个参数

    reduce从数组的正方向(0/1/2.....length-1)开始,reduceRight从数组的反方向(length-1/length-2/.....0)开始

    func原形

    function func(lastResult, value);

    参数含义

    • lastResult: 上轮计算的结果, 第一次调用时, 此值为initValue(reduce的第二个参数, 如果有 )或者arr[0](当没有传入initValue时, 会取数组的第一个元素, 如果是reduceRight, 为最后一个元素 )
    • value: 当前轮的元素值

    实例:

    var arr = [1,2,3,4,5];
    function func1(lastResult, value){
      return lastResult + value;
    }
    console.log(arr.reduce(func1)); // => 15
    

    对应的js实现:

    function myReduce(a, func, initValue){
      var rtn = initValue || a[0];
      for(var i = initValue?0:1; i < a.length; i++){
        rtn = func(rtn, a[i]);
      }
      return rtn;
    }
    function myReduceRight(a, func, initValue){
      var rtn = initValue || a[a.length - 1];
      for(var i = initValue?(a.length - 1):(a.length - 2); i >=0; i--){
        rtn = func(rtn, a[i]);
      }
      return rtn;
    }
    console.log(myReduce(arr, func1,0));  // => 15
    console.log(myReduceRight(arr, func1,0));  // => 15
    

    indexOf和lastIndexOf - 搜索

    arr.indexOf(value);
    arr.lastIndexOf(value);

    搜索整个数组中具有给定值(value)的元素, 并返回第一次找到的元素所在的索引, 如果没有找到返回-1;
    有些朋友可能记得字符串对象中有这两个方法, 其实这里的用法和字符串是一样的
    下面直接看实例:

    var arr = [1,2,3,2,1];
    console.log(arr.indexOf(2)); // => 1
    console.log(arr.lastIndexOf(2)); // => 3
    

    对应js实现

    function myIndexOf(a, value){
      for(var i = 0; i < a.length; i++){
        if(a[i] === value){
          return i;
        }
      }
      return -1;
    }
    function myLastIndexOf(a, value){
      for(var i = a.length - 1; i >=0; i--){
        if(a[i] === value){
          return i;
        }
      }
      return -1;
    }
    console.log(myIndexOf(arr, 2));  // => 1
    console.log(myLastIndexOf(arr, 2));  // => 3
    

    Array.isArray - 判断对象是否为数组对象

    这是一个静态方法, 用来判断参数是否为数组对象, 例如

    console.log(Array.isArray([]));  // => true
    console.log(Array.isArray({})); // => false
    

    对应的js实现代码

    var isArray = Function.isArray || function (o){
        return typeof o === "object" && Object.prototype.toString.call(o) === "[object Array]";
      }
    console.log(isArray([]));  // => true
    console.log(isArray({})); // => false
    

    相关文章

      网友评论

        本文标题:ECMAScript 5中的数组方法

        本文链接:https://www.haomeiwen.com/subject/ikailttx.html