美文网首页
深入理解数组内置方法

深入理解数组内置方法

作者: fangdown | 来源:发表于2017-09-01 11:47 被阅读0次

    数组的方法大概分es3、es5、es6版本了,各个版本都有一些新的定义。
    鉴于es5 已经成为当前主流标准,所以不区分es3 和es5了,直接区分es5和es6。

    es5数组内置方法:
    1,Array.prototype.push(itemX, itemY) ---向数组的末尾添加一个或更多元素,并返回新的长度。
    2,Array.prototype.pop() --删除并返回数组的最后一个元素。
    3,Array.prototype.unshift(itemX, itemY) -- 向数组的开头添加一个或更多元素,并返回新的长度。
    4,Array.prototype.shift() -- 删除并返回数组的第一个元素。
    5,Array.prototype.concat(arrayX,arrayX,......,arrayX) --连接两个或更多的数组,并返回结果,把后面的数组追加到第一个数组。
    6,Array.prototype.join(指定分隔符) -- 把数组的所有元素放入一个字符串。元素通过指定的分隔符进行分隔。
    6.1,String.prototype.split(指定分隔符) -- 把字符串通过指定分隔符形成数组
    7,Array.prototype.reverse() -- 颠倒数组中元素的顺序。
    8,Array.prototype.sort(sortby) --对数组的元素进行排序
    8,Array.prototype.slice(start, end) --从某个已有的数组返回选定的元素
    9,Array.prototype.splice(index,howmany,item1,.....,itemX) --删除元素,并向数组添加新元素。
    10,Array.prototype.toString() --把数组转换为字符串,并返回结果。
    11,Array.prototype.toLocaleString() --把数组中每一元素转换为本地字符串,再拼接,返回结果,主要是时间类。
    12,Array.prototype.valueOf --返回数组对象的原始值,内部用,其实就是返回它自己
    13,Array.prototype.toSource --返回该对象的源代码。// 大部分不支持

    新增方法(存在ie6-ie8不兼容问题):

    14,Array.prototype.forEach() --是Array新方法中最基本的一个,就是遍历,循环
    15,Array.prototype.map() --原数组被“映射”成对应新数组
    16,Array.prototype.filter() -- 根据过滤条件对原数组进行过滤,形成新数组
    17,Array.prototype.some() --是否“某些项”合乎条件 返回true/false
    18,Array.prototype.every() --是否都符合条件 返回true/false
    19,Array.prototype.indexOf() --包含指定元素的第一个位置
    20,Array.prototype.lastIndexOf() --从数组后面找到该元素的第一个位置
    21,Array.prototype.reduce() --迭代”、“递归(recursion), 返回一个回调函数结果
    22,Array.prototype.reduceRight() --从数组的末端开始迭代”、“递归(recursion), 返回一个回调函数结果

    改变数组的方法有以下

    push
    pop
    unshift
    shift
    splice
    reverse
    sort

    重点讲几个方法,存在混淆点

     // push 可以向尾部添加1个或者多个
    var arr = [1, 2, 3];
    arr.push(4, 5) // arr = [1, 2, 3, 4, 5] 以前都是插入单个,还未插入多个
    // unshift 可以向头部添加1个或者多个
    arr.unshift(4, 5) // arr = [4, 5, 1, 2, 3, 4, 5]
    //concat 并不会改变数组
    var arr2 = [10, 11];
    var arr3 = arr.concat(arr2) // arr 和 arr2并不会发生变化
    //sort(sortby) sortby 是一个函数,返回值为大于0 小于0 等于0
    sortby = function(a, b){
      return a-b;
     //a -b > 0   a排在b后面
     // a-b = 0 不换位置
     // a-b < 0 a在b前面
    }
    // slice(start, end) start,end 说明
    /**
    start 必选 ,end可选
    */
    var arr = [1, 2, 3, 4];
    //start 取值情况
    var arr4 = arr.slice(0, 1) //   arr4 = 1  从0开始,截取1位
    var arr4 = arr.slice(1, 1) //   arr4 = 2  从1开始,截取1位
    var arr4 = arr.slice(-1, 1) //   arr4 = 4  从倒数第一位开始,截取1位
    var arr4 = arr.slice(5, 1) //   arr4 = []  超出数组长度,返回空数组
    // end 取值情况
    var arr4 = arr.slice(1) //   arr4 = [2, 3, 4]  end为空,从第一位开始,截取剩下的元素
    var arr4 = arr.slice(1, 0) // arr4 = [] ,截取0个元素时,返回空数组
    var arr4 = arr.slice(1,10) //arr4 = [2, 3, 4]  end超出数组长度时,截取剩下的元素
    var arr4 = arr.slice(1, -1) //arr4 = [2, 3] end为负数时,截取到数组长度+负数的位置,不包含该位置
    var arr4 = arr.slice(-1, -1) // arr4 = [] start end 均为负数时,以start为开始,若end在start前返回空,在start后,获取剩下元素
    
    //splice(index,howmany,item1,.....,itemX)
    /**
    index: 起始位
    howmany: 多少个
    item1...itemx:插入值
    */
    var arr = [1, 2, 3, 4];
    arr.splice(0) // arr = [] 为一个或两个参数时,是删除操作
    arr.splice(1) // arr = [2, 3, 4]
    arr.splice(-1) // arr = [1, 2, 3] 当index为负值时,则从length+index位开始计算
    arr.splice(-2, 1) // arr = [1, 2, 4] 
    arr.splice(1, 0) //arr = [1, 2, 3 ,4] 为0时不删除
    arr.splice(1, 5) // arr = [1] 超出长度,以最大长度计算
    arr.splice(1, 1, 10) // arr = [1,10, 3, 4] 先删除,然后在指定位置插入值
    arr.splice(1, 1, 10,20) // arr = [1,10,20, 3, 4]  有多个则依次插入多个
    arr.splice(10, 1, 555) // arr = [1, 2, 3, 4, 555] 起始值超出长度时,则在最后面插入
    

    es6的方法演示及兼容写法

    1. forEach(callback,[ thisObject])
      callback回调函数 = function (item, index ,array)
      thisObject 一个可选的上下文参数(改变回调函数里面的this指向)
      var data = {
      users: ['张含韵', '李小璐', '白百何'],
      sendEmails: function(user){
        if(this.isValidUser(user)){
          console.log('你好' + user);
        } else {
          console.log('你好不是本家人')
        }
      },
      isValidUser: function(user){
        return /^张/.test(user)
      }
    }
    data.users.forEach(data.sendEmails, data)
     //此时,如果不带data,会报错的,执行sendEmails方法用到this.isValidUser方法,此时this指向window,带了data,指向data
    //jquery中也有each方法。容易混淆
    $.each([], function(index, item, array) {
        // ...
    });
    //回调函数中的参数 第一位和第二位与数组中的顺序恰恰相反,使用的时候要注意一下
    // 兼容IE6-8
    if(typeof Array.prototype.forEach !== 'function'){
      Array.prototype.forEach = function(fn, context){
        for(var k = 0, len = this.length; k < len; k++){
          if(typeof fn === 'function' && Object.prototype.hasOwnProperty.call(this, k)){
            fn.call(context, this[k], k, this)
          }
        }
      }
    }
    //this指向的是调用的数组
    
    1. array.map(callback,[ thisObject]); //返回新数组
    [].map(function(value, index, array) {
        // ...
    });
    var arr = [1, 2, 3];
    var arr2 = arr.map(function(value, index, array){
       return value  * 2 // 必须要return 否者返回 undefined
    })
    // arr2  = [2, 4, 6]
    // 兼容IE6-8
    if(typeof Array.prototype.map != 'function'){
      Array.prototype.map = function(fn, context) {
        var arr = [];
        if(typeof fn === 'function' ){
          for(var k = 0, len = this.length; k < len; k++){
              arr.push(fn.call(context, this[k], k, this))
          }
        }
        return arr;
      }
    }
    

    3.array.filter(callback,[ thisObject]); //返回符合条件的新数组
    if(typeof Array.prototype.map != 'function'){
    Array.prototype.map = function(fn, context) {
    var arr = [];
    if(typeof fn === 'function' ){
    for(var k = 0, len = this.length; k < len; k++){
    fn.call(context, this[k], k, this) && arr.push(this[k]) //fn返回为真 则插入该值
    }
    }
    return arr;
    }
    }

    1. array.some(callback,[ thisObject]); // 其中某项符合, 返回true/false
      var arr = [1, 4, 8];
      var result = arr.some(function(item, index ,array){
          if(item > 4){
            return true;
          }
      })
      result === true
    // 兼容IE6-8
    if(typeof Array.prototype.some!= 'function'){
      Array.prototype.some = function(fn, context) {
        var passed = false;
        if(typeof fn === 'function'){
          for(var k = 0, len = this.length; k < len; k++){
            if(passed === true) {
              break;
            } 
            passed = !!fn(context, this[k], k, this);
          }
        }
    return passed
      }
    }
    
    1. every(callback,[ thisObject]); //全部符合,返回true/false
       var arr = [1, 4, 8];
      var result = arr.every(function(item, index ,array){
          if(item > 4){
            return true;
          }
      })
      result === false
    // 兼容IE6-8
    if(typeof Array.prototype.every!= 'function'){
      Array.prototype.every= function(fn, context) {
        var passed = true;
        if(typeof fn === 'function'){
          for(var k = 0, len = this.length; k < len; k++){
            if(passed === false) {
              break;
            } 
            passed = !!fn(context, this[k], k, this);
          }
        }
        return passed
      }
    }
    
    1. array.indexOf(searchElement[, fromIndex])
      indexOf方法在字符串中自古就有,string.indexOf(searchString, position)。数组这里的indexOf方法与之类似。
      返回整数索引值,如果没有匹配(严格匹配),返回-1. fromIndex可选,表示从这个位置开始搜索,若缺省或格式不合要求,使用默认值0,我在FireFox下测试,发现使用字符串数值也是可以的,例如"3"和3都可以。
    var data = [2, 5, 7, 3, 5];
    
    console.log(data.indexOf(5, "x")); // 1 ("x"被忽略)
    console.log(data.indexOf(5, "3")); // 4 (从3号位开始搜索)
    
    console.log(data.indexOf(4)); // -1 (未找到)
    console.log(data.indexOf("5")); // -1 (未找到,因为5 !== "5")
    // 兼容IE6-8
    if (typeof Array.prototype.indexOf != "function") {
      Array.prototype.indexOf = function (searchElement, fromIndex) {
        var index = -1;
        fromIndex = fromIndex * 1 || 0;
    
        for (var k = 0, length = this.length; k < length; k++) {
          if (k >= fromIndex && this[k] === searchElement) { //大于起始位且相等
              index = k;
              break;
          }
        }
        return index;
      };
    }
    
    1. array.lastIndexOf(searchElement[, fromIndex])
      lastIndexOf方法与indexOf方法类似:只是lastIndexOf是从字符串的末尾开始查找,而不是从开头。还有一个不同就是fromIndex的默认值是array.length - 1而不是0.
    if (typeof Array.prototype.lastIndexOf != "function") {
      Array.prototype.lastIndexOf = function (searchElement, fromIndex) {
        var index = -1, length = this.length;
        fromIndex = fromIndex * 1 || length - 1;
    
        for (var k = length - 1; k > -1; k-=1) {
            if (k <= fromIndex && this[k] === searchElement) {
                index = k;
                break;
            }
        }
        return index;
      };
    }
    var data = [2, 5, 7, 3, 5];
    
    console.log(data.lastIndexOf(5)); // 4
    console.log(data.lastIndexOf(5, 3)); // 1 (从后往前,索引值小于3的开始搜索)
    
    console.log(data.lastIndexOf(4)); // -1 (未找到)
    
    1. array.reduce(callback[, initialValue])
      callback函数接受4个参数:之前值、当前值、索引值以及数组本身。initialValue参数可选,表示初始值。若指定,则当作最初使用的previous值;如果缺省,则使用数组的第一个元素作为previous初始值,同时current往后排一位,相比有initialValue值少一次迭代。
    var sum = [1, 2, 3, 4].reduce(function (previous, current, index, array) {
      return previous + current;
    });
    
    console.log(sum); // 10
    

    说明:

    因为initialValue不存在,因此一开始的previous值等于数组的第一个元素。
    从而current值在第一次调用的时候就是2.
    最后两个参数为索引值index以及数组本身array.
    执行过程:
    // 初始设置
    previous = initialValue = 1, current = 2

    // 第一次迭代
    previous = (1 + 2) = 3, current = 3

    // 第二次迭代
    previous = (3 + 3) = 6, current = 4

    // 第三次迭代
    previous = (6 + 4) = 10, current = undefined (退出)

    var matrix = [
      [1, 2],
      [3, 4],
      [5, 6]
    ];
    
    // 二维数组扁平化
    var flatten = matrix.reduce(function (previous, current) {
      return previous.concat(current);
    });
    
    console.log(flatten); // [1, 2, 3, 4, 5, 6]
    // 兼容ie6-8
    if (typeof Array.prototype.reduce != "function") {
      Array.prototype.reduce = function (callback, initialValue ) {
         var previous = initialValue, k = 0, length = this.length;
         if (typeof initialValue === "undefined") {
            previous = this[0];
            k = 1;
         }
         
        if (typeof callback === "function") {
          for (k; k < length; k++) {
             this.hasOwnProperty(k) && (previous = callback(previous, this[k], k, this));
          }
        }
        return previous;
      };
    }
    
    1. array.reduceRight(callback[, initialValue])
      reduceRight是从数组的末尾开始实现
    var data = [1, 2, 3, 4];
    var specialDiff = data.reduceRight(function (previous, current, index) {
      if (index == 0) {
        return previous + current;
      }
      return previous - current;
    });
    
    console.log(specialDiff); // 0
    

    // 初始设置
    index = 3, previous = initialValue = 4, current = 3

    // 第一次迭代
    index = 2, previous = (4- 3) = 1, current = 2

    // 第二次迭代
    index = 1, previous = (1 - 2) = -1, current = 1

    // 第三次迭代
    index = 0, previous = (-1 + 1) = 0, current = undefined (退出)

    if (typeof Array.prototype.reduceRight != "function") {
      Array.prototype.reduceRight = function (callback, initialValue ) {
        var length = this.length, k = length - 1, previous = initialValue;
        if (typeof initialValue === "undefined") {
            previous = this[length - 1];
            k--;
        }
        if (typeof callback === "function") {
           for (k; k > -1; k-=1) {          
              this.hasOwnProperty(k) && (previous = callback(previous, this[k], k, this));
           }
        }
        return previous;
      };
    }
    

    应用场景举例:
    var eleDivs = document.getElementsByTagName("div");
    Array.prototype.forEach.call(eleDivs, function(div) {
    console.log("该div类名是:" + (div.className || "空"));
    });

    相关文章

      网友评论

          本文标题:深入理解数组内置方法

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