js数组

一曲冷凌霜 提交于 2020-02-07 05:07:17

数组

  • 数组是一个引用列表(顺序,只有值,紧密,速度慢)

数组的创建

var array=[]; //创建空数组
var array=new Array(); //构造函数创建法
var arr=Array(); //不是创建方法,只是把字符串转化为数组类型,速度慢点儿
var arr=new Object([]); //对象数组,不建议使用,反正也还没用过

构造函数创建

  • 构造函数实例化对象
    var arr=new Array(1,2,3,4,5);
    console.log(arr);
    数组通过构造函数创建时,如果只有一个参数,并且参数是正整数,这个数就是数组的长度,而不作为数组的新元素;
    如果是数字,但不是正整数,都会报错; 如果不是数字,则作为数组的第一个元素添加。
    var arr=new Array(“3”);
    console.log(arr); //[“3”]
    var arr=new Array(9);
    console.log(arr); //(9) [empty × 9]
  • 字符串转数组类型
    var arr=Array(1,2,3,4,5,6);
    console.log(arr);
    var arr=Array(5);
    console.log(arr); //(5) [empty × 5]

数组的结构

  • 字面量创建数组
    var arr0 = [1,2,3,4,5];两个","之间的那个是空元素。
    var arr=[1,2,3,4,5];
    arr是数组 1是索引值(下标) arr[1]元素(下标变量)。
    console.log(arr[1]);
    arr[1]=10; //可以修改下标变量的结果
    console.log(arr[1]);

  • 数组的紧密性
    arr[“5”]=10;
    arr[7]=10; //如果下标值>数组长度-1,会创建空元素来补齐
    console.log(arr); //(8) [1, 10, 3, 4, 5, 10, empty, 10]
    另外用delete删除数组元素时,不会造成数组的自动收缩,紧密,数组的长度不会发生改变:
    delete arr[2];
    console.log(arr);//(5) [1, 2, empty, 4, 5]

  • 数组只有值存储,只能遍历数组获取值是否存在
    for(var i=0;i<5;i++){
    console.log(arr[i]);
    }
    console.log(arr);

  • 遍历内容较多时,当添加删除元素时,因为数组紧密性,速度变慢,尤其是在数组靠前位置插入和删除。

数组的长度 length

  1. console.log(arr.length); //表示当前数组得索引下标的最大值+1,因为从0开始
    arr[arr.length]=10; //会在数组尾部添加一个值为10的新元素,数组长度亦+ 1。
    每次添加元素后,长度会发生改变,length会变化的,因此上面这句不会修改最后一个元素,而是添加一个新元素;
    arr[arr.lenght-1]; //代表最后一个元素;
  2. 当添加不是索引数据(0开始),比如arr[-1],不会累计在长度中,而作为对象的key,value增加内容。
    arr[-1]=10; //arr["-1"]=10;这样表示也行
    console.log(arr); //[1, 2, 3, 4, 5, -1: 10]有对象的用法吧
  3. arr.length=8; //直接设置数组的长度,length>原有长度,则添加空元素补齐,使长度为length=8。
    arr.length=10;
  4. arr.length=arr.length-1; //如果长度比原来少一个,就会删除最尾部元素
    arr.length–;
    arr.length=0; //表示清空数组
    绝对不能 arr=[]; //引用地址变化了,arr原来指向的内容变成孤儿对象了,相当于重新创建数组
  5. 数组长度—报错的情况
    arr.length=-2; //数组的长度不能为负值,报错:Invalid array length
    arr.length=“a”;
    arr.length=true; //如果给的不是数值,会隐式转换为数值,如果值是NaN,就会报错
    console.log(arr,arr.length);

判断是否是数组

判断是不是数组的几种方法:
ES6
console.log(Array.isArray(arr)); //true
ES5
console.log(Object.prototype.toString.call(arr)= = = “[object Array]”);
console.log(arr.constructor===Array); //常用方法,推荐使用

数组的方法

创建一个数组:var arr=[1,2,3];

1、push

  • 数组尾部添加一个or多个新元素,且返回数组的新长度。
    console.log(arr.push(4,5)); //5
  • push重构
function push(arr){
    for(var i=1;i<arguments.length;i++){
        arr[arr.length]=arguments[i];
    }
    return arr.length;
}
console.log(arr,push(arr,4,5));  //(5) [1, 2, 3, 4, 5]5

2、pop

  • 删除数组尾部元素,且返回被删除的元素。
    console.log(arr.pop()); //3
  • pop重构
function pop(arr){
    var value=arr[arr.length-1];
    arr.length--;
    return value;
}
console.log(pop(arr));   //3

3、unshift()

  • 添加一个或多个新元素在数组的最前面,且返回数组的新长度。
    console.log(arr,arr.unshift(-1,0)); //(5) [-1, 0, 1, 2, 3] 5
  • unshift重构
function unshift(arr){
    var len=arguments.length-1;  //arguments[0]是arr参数
    for(var i=arr.length-1;i>=0;i--){
        arr[i+len]=arr[i];   //将arr的每个元素往后移添加的元素个数位
    }
    for(var i=1;i<arguments.length;i++){
        arr[i-1]=arguments[i];   //将新添加的元素依次放入arr最前面
    }
    return arr.length;
}
console.log(arr,unshift(arr,-1,0));  //(5) [-1, 0, 1, 2, 3] 5

4、shift()

  • 删除数组的第一个元素,且返回该元素。
    console.log(arr.shift()); //-1
  • shift重构
function shift(arr){
    var value=arr[0];
    for(var i=0;i<arr.length-1;i++){
        arr[i]=arr[i+1];
    }
    arr.length--;
    return value;
}
console.log(arr,shift(arr));   //(4) [0, 1, 2, 3] -1

5、concat()

  • 复制
  • 复制后给新数组添加新元素或新数组
  • 连接,多个数组连接形成新数组
  • 不改变原数组
var arr = [1, 2, 3, 4, 5];
var arr2=arr.concat();  //相当于复制
console.log(arr2,arr);  //(5) [1, 2, 3, 4, 5] (5) [1, 2, 3, 4, 5]  
var arr1=arr.concat(9,8,9,0,1);  //复制后添加新元素到新数组的尾部
console.log(arr1,arr);  //(10) [1, 2, 3, 4, 5, 9, 8, 9, 0, 1] (5) [1, 2, 3, 4, 5] 
var arr3=arr.concat([11,22],[111,222]);  //多个数组连接形成新数组赋值给arr3,arr不变
console.log(arr3,arr); //(9) [1, 2, 3, 4, 5, 11, 22, 111, 222] (5) [1, 2, 3, 4, 5]
  • concat重构
// 我用的for in,不过注意,for in遍历的话会自动忽略空元素,
// 所以不要学我,还是老老实实用for循环吧
// 我以后也会用for的
function concat(arr){
    var array=[];
    for(var prop in arr){
        array[prop]=arr[prop];
    }
    for(var i=1;i<arguments.length;i++){
        if(arguments[i].constructor===Array){
            for(var prop in arguments[i]){
                array[array.length]=arguments[i][prop];
            }
        }else{
            array[array.length]=arguments[i];
        }
    }
    return array;
}
//for循环来实现
function concat(arr){
    var array=[];
    var index=0;
    for(var i=0;i<arr.length;i++,index++){
        array[index]=arr[i];
    }
    for(var j=1;j<arguments.length;j++,index++){
        if(arguments[j].constructor===Array){
            for(var k=0;k<arguments[j].length;k++,index++){
                array[index]=arguments[j][k];
            }
            index--;//因为多加了一次,要判断k<arguments[j].length,index也跟着增加了
        }else{
            array[index]=arguments[j];
        }
    }
    return array;
} 
//for循环简化
function concat(arr){
    var array=[];  //空数组的长度即array.length默认为0
    for(var i=0;i<arr.length;i++){
        array[array.length]=arr[i];
    }
    for(var j=1;j<arguments.length;j++){
        if(arguments[j].constructor===Array){
            for(var k=0;k<arguments[j].length;k++){
                array[array.length]=arguments[j][k];
            }
        }else{
            array[array.length]=arguments[j];
        }
    }
    return array;
} 
console.log(concat(arr,11,22,33),arr);//(8) [1, 2, 3, 4, 5, 11, 22, 33] (5) [1, 2, 3, 4, 5]
console.log(arr.concat(11,22,33));//(8) [1, 2, 3, 4, 5, 11, 22, 33]
console.log(concat(arr,11,arr,22,33,arr));// [1, 2, 3, 4, 5, 11, 22, 33, 1, 2, 3, 4, 5]
console.log(arr.concat(11,arr,22,33,arr));// [1, 2, 3, 4, 5, 11, 22, 33, 1, 2, 3, 4, 5]
console.log(arr.concat(11,22,33,arr));//(8) [1, 2, 3, 4, 5, 11, 22, 33]
var arr1=concat(arr,[10,11,12],0,[13,14,15]);//(12) [1, 2, 3, 4, 5, 10, 11, 12, 0, 13, 14, 15]
console.log(arr1);

6、join()

  • 转化为字符串
  • 用符号(参数)分割产生字符串
  • 不改变原数组
console.log(arr.join("#"),arr);//1#2#3#4#5 (5) [1, 2, 3, 4, 5]
  • join重构
function join(arr){
    var str=""
    for(var i=0;i<arr.length;i++){
        if(arguments[1]==null) arguments[1]=",";  //设置默认分隔符为","
        str+= i==arr.length-1?arr[i]:arr[i]+arguments[1]+""; //+""要转化为字符串
    }
    return str;
}
console.log(join(arr,"#"));//1#2#3#4#5

7、splice(起始位置,删除元素个数,添加的新元素)

  • 改变原数组
  • 此起始位置为下标从0开始,包含此起始位置。
  • 给数组中添加、删除、替换一个或多个元素,返回被删除元素组成的数组
  • 创建一个空数组
    var arr1=arr.splice(); //没有被删元素,arr1=[ ];
  • 传递数组arr的所有元素传递给新数组
    var arr1=arr.splice(0);
  • 参数为负数意为 从后向前数
    var arr1=arr.splice(-2); //从数组的倒数第二位开始截取到尾部。
  • 删除、添加、替换元素
var arr = [1, 2, 3, 4, 5];
//从第二位开始删除2个元素。
var arr1=arr.splice(2,2);  
console.log(arr1, arr);  //(2) [3, 4] (3) [1, 2, 5]
//插入元素12,14在第二位。
console.log(arr.splice(2,0,12,14));  //(7) [1, 2, 12, 14, 3, 4, 5]
//替换元素,删除两位,并插入12,14
var arr1=arr.splice(2,2,12,14);  
console.log(arr1,arr);  //(2) [3, 4] (5) [1, 2, 12, 14, 5]
//如果删除的个数为非数值,则先转化为数值,再进行判断
var arr1=arr.splice(1,true,22);
console.log(arr1, arr);  //[2] (5) [1, 22, 3, 4, 5]
//如果删除的个数为NaN,则不删除
var arr1=arr.splice(1,"d",22);
console.log(arr1, arr);  //[] (6) [1, 22, 2, 3, 4, 5]
  • splice重构
    (备注:太复杂,没懂,先放一放)。
function splice(arr, start, count) {
    var array = [];
    start = Number(start);//以防传进来的参数非数值
    count = Number(count);
    if (isNaN(start)) return array;
    if (start < 0) start += arr.length; //如果是负数,意为倒数第几位开始,为了方便,全部更改成正数模式
    if(isNaN(count)) count=0;  //如果删除的个数为NaN,则不删除
    if (count < 0) count=0;
    //把删除掉的元素拿出来放到array里面
    for(var i=start,j=0;i<arr.length;i++,j++){
        if(j<count) array.push(arr[i]);
        arr[i]=arr[i+count];
    }
    for(var i=0;i<arguments.length-3;i++){
        for(var j=arr.length-1;j>=start+i;j--){
            arr[j+1]=arr[j];
        }
    }
    for(var i=3;i<arguments.length;i++){
        arr[start+i-3]=arguments[i];
    }
    //最后把多出来的元素去掉
    for(var i=0;i<count;i++){
        arr.length--;
    }
    return array;
}
var arr1=splice(arr,2,2,10,11,34);
console.log(arr1,arr);  //(2) [3, 4] (6) [1, 2, 10, 11, 34, 5]

8、slice(起始位置,截止什么位置之前);

  • 不改变原数组
  • 此起始位置为下标从0开始,包含此起始位置;
  • 截取复制,返回一个新数组
  • 复制一个新数组,没有引用关系
    var ar1=arr.slice(); //默认从头复制到尾
  • 其他用法
var arr = [1, 2, 3, 4, 5];
var arr1=arr.slice(1);  //从第几项复制到尾部 (4) [2, 3, 4, 5]
var arr1=arr.slice(-2);  //从倒数第二位复制到尾部 (2) [4, 5] 
var arr1=arr.slice(2,3);  //从第二位复制到第三位之前 [3] 
var arr1=arr.slice(-3,-1);  //从倒数第三位复制到倒数第一位之前 (2) [3, 4]
var arr1=arr.slice(2,-1);   //从第二位复制到倒数第一位之前 (2) [3, 4]
console.log(arr1);
  • slice重构
function slice(arr, start, end) {
    start = Number(start);
    end = Number(end);
    if (isNaN(start)) start = 0;
    if (isNaN(end)) end = arr.length;
    if (start < 0) start=start+arr.length;
    if (end < 0) end=end+arr.length;
    var array=[];
    for(var i=start,j=0;i<end;i++,j++){
        array[j]=arr[i];
    }
    return array;
}
console.log(slice(arr,2,arr.length-1));  //(2) [3, 4]

9、indexOf

  • arr.lastIndexOf(要查找的元素,从第几位开始查找包含此位);
    查找元素在数组中的下标,如果没有查找到,则返回-1。
    var arr=[1,2,2,4,3,4,5,4,2,6,2,7];
    console.log(arr.indexOf(4)); //3 所查找的4,第一次出现下标为3
    console.log(arr.indexOf(4,4)); //5 查找4,从第4位开始查找(注意,下标从0开始)
    console.log(arr.indexOf(14,4)); //-1 没找到14

  • arr.lastIndexOf(要查找的元素,从第几位开始查找包含此位);
    从后向前查找。
    lastIndexOf() 方法可返回一个指定的元素在数组中最后出现的位置,从该字符串的后面向前查找。如果要检索的元素没有出现,则该方法返回 -1。
    console.log(arr.lastIndexOf(6)); //9
    console.log(arr.lastIndexOf(6,3)); //-1 从下标3开始往前查找,未查找到6

  • 查找元素出现时的所有下标

原理解释:
~ arr.indexOf(2); //比如说找2,没找到返回-1,只有~(-1)=0,其他都不是0;
所以 if(~arr.indexOf(value)) 意为当不是-1即找到value值时进入条件;
if(!~arr.indexOf(value)) 意为当没找到值时进入条件。

var arr=[1,2,2,4,3,4,2,,5,4,2,6,2,7];
var index=-1;
while(~(index=arr.indexOf(2,index+1))){
    //当找到进入条件,直到查找结束;
    //找到时,把下标赋值给index,下次循环开始,直接跳到被找到下标的下个下标,避免了重复打印
    //没找到返回-1,而~(-1)=0,不进入条件。
    console.log(index)
} 
//用for循环解释一下
for(var i=0;i<arr.length;i++){
    if(~(arr.indexOf(2,i))) {
        console.log(arr.indexOf(2,i));
        i=arr.indexOf(2,i);
    }
}
  • 数组去重
    因为数组的严密性,每次删除一个元素,就得动很多其他元素;
    因此可以创建一个新数组,将符合要求的数给新数组,再重新给原数组赋值;
    如果没有写在函数中,那么不要忘了把新数组最后置null,给垃圾回收掉。
var arr=[1,2,2,3,4,3,4,5,4,2,6,2,7,8];
function nonRep(arr){
    var arr1=[];
    for(var i=0;i<arr.length;i++){
        if(arr1.indexOf(arr[i])<0) arr1.push(arr[i]); //将arr[i]的值与arr1里的比较
    }
    arr=arr1.splice(0);
    //arr1=null; //函数执行完毕局部变量arr1会被销毁,无须再写
    return arr;
}
console.log(nonRep(arr));//(8) [1, 2, 3, 4, 5, 6, 7, 8]

不用indexOf的话,方法如下:

var arr=[1,2,2,4,3,4,5,4,2,6,2,7];
var arr1=[];
for(var i=0;i<arr.length;i++){
    var bool=false;
    for(var j=0;j<arr1.length;j++){
        if(arr[i]===arr1[j]){
            bool=true;
            break;
        }
    }
    if(!bool){
        arr1.push(arr[i]);
    }
}
arr=arr1.splice(0);
arr1=null; //没有写在函数中,不会自动被销毁,所以就手动回收呗
console.log(arr);  //(7) [1, 2, 4, 3, 5, 6, 7]

数组的遍历

1、说到数组的遍历,先说说 for in 和 for循环:
for in 循环可以把数组的可枚举属性遍历到,但不能遍历到数组的空元素。null可以遍历到,因为null不属于空元素。
for循环可以遍历到空元素,但是空元素会被打印为undefined。
for与for in的比较

var arr1=[11,22,33,44,,66];
console.log(arr1);//(6) [11, 22, 33, 44, empty, 66] 打印,空元素被打印成empty
//for in
for(var prop in arr1){
    console.log(arr1[prop]);//遍历不到空元素
}
//for
for(var i=0;i<arr1.length;i++){
    console.log(arr1[i]);//空元素会被打印为undefined
}

2、数组的去重遍历

跟之前介绍的一样,delete删除的元素会被替换成empty,数组长度不变。

var arr=[1,1,2,2,4,3,4,5,4,2,6,2,7];
//先将重复的元素删除掉,注意数组长度不变,删除的元素会用empty占位
for(var i=0;i<arr.length;i++){
    if(arr.indexOf(arr[i],i+1)>-1) delete arr[i];//保留重复出现元素值的最后一个
    // if(arr.lastIndexOf(arr[i],i-1)>-1) delete arr[i];  /*保留重复出现元素值的第一个*/
}
//for in会自动忽略空元素
var arr1=[];
for(var prop in arr){
    arr1.push(arr[prop]);
}
arr=arr1.splice(0);
arr1=null;
console.log(arr);  //(7) [1, 3, 5, 4, 6, 2, 7]

3、数组还有两个方法常用来只做遍历。

10、forEach() 遍历
  • 不遍历空元素,也不遍历属性;
  • 匿名函数,无法阻止它在循环中中断循环跳出;
var arr = [2, 4, 6, 8, 10, , 12, 14, 16, 18, 20];
arr.forEach(function (item, index, a) {
    if(index===2) return; //遍历不会中断,但是会跳过下标为2的元素
    console.log(item, index, a); ////依次为元素、索引、数组;此处遍历,共打印arr.length次;若元素值为空,则不会遍历到此元素,直接跳过此元素
});
  • 不返回任何值;
  • forEach重构
function forEach(arr,fn){
    for(var i=0;i<arr.length;i++){
        if(arr[i]===undefined) continue; //空元素不遍历
        fn(arr[i],i,arr);
    }
}
// 桥接模式
forEach(arr,function(item,index,a){
    console.log(item,index,a);
});
11、map() 遍历
  • 将回调函数return的结果,返回到新数组中;
    map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
    map() 方法按照原始数组元素顺序依次处理元素。
  • 不会对空数组进行检测(但空元素依然存在)。
  • 不改变原数组。
var arr = [1,2,,3];
var a=arr.map(function(item,index,a){
    // console.log(item,index,a); //与forEach打印结果并无二致
    return item+100;
});
console.log(a,arr); //(4) [101, 102, empty, 103] (4) [1, 2, empty, 3]
  • map重构
function map(arr,fn){
    var array=[];
    for(var i=0;i<arr.length;i++){
        if(arr[i]===undefined) continue; //不检测空元素
        array[i]=fn(arr[i],i,arr);
    }
    return array; //返回新数组
}
var a=map(arr,function(item,index,a){
    return item+1000;
});
console.log(a,arr); //(4) [1001, 1002, empty, 1003] (4) [1, 2, empty, 3]

12、some()

遍历数组,查找是否满足条件,若满足条件,就直接跳出遍历,返回true;若不满足条件,返回false。

var arr=[1,2,3,4,5];
var bool = arr.some(function (item, index, a) {
    return item > 4;
});
console.log(bool);  //true
  • some重构
function some(arr,fn){
    for(var i=0;i<arr.length;i++){
        if(arr[i]===undefined) continue; //不检测空元素
        if(fn(arr[i],i,arr)) return true;
    }
    return false;
}
var bool=some(arr,function(item,index,a){
    return item>10;
});
console.log(bool); //false

13、every()

遍历数组,判断每一个是否都满足条件,如果有一个不满足,直接返回false。

var arr=[1,2,3,4,5];
var bool=arr.every(function(item,index,arr){
	//参数index,arr可以省略,等用到的时候再写也行
    return item>0;
});
console.log(bool); //true
  • every重构
function every(arr,fn){
    for(var i=0;i<arr.length;i++){
        if(arr[i]===undefined) continue; //不检测空元素
        if(!fn(arr[i],i,arr)) return false; //如果有一个元素不满足条件而返回false,则!false==true,就会执行return false语句,直接返回false
    }
    return true;
}
var bool=every(arr,function(item){
    return item>4;
});
console.log(bool);  //false

(注意:有个小案例,全选问题,请看下面 "非数组列表转化为数组"中的示例)

14、arr.fill() 填充元素

fill填充,只适用于构造函数创建的数组中
var arr1=new Array(3);
console.log(arr1.fill(100));//(3) [100, 100, 100]

15、filter() 筛选

  • 筛选出符合条件的
  • 返回数组,包含了符合条件的所有元素。如果没有符合条件的元素则返回空数组。
  • 不改变原数组
var i = 0;
var arr = [1, 2,, 2, 4, 3, 4, 5, 4, 2, 6, 2, 7];
var arr1 = arr.filter(function (item, index, a) {
    console.log(item,index,a); //不检测空元素,跳过空元素
    if (item === 2)
        i++;
    return item > 2; //返回满足条件的所有元素
});
console.log(arr1, i, arr.length,arr); //(7) [4, 3, 4, 5, 4, 6, 7] 4 13 (13) [1, 2, empty, 2, 4, 3, 4, 5, 4, 2, 6, 2, 7]
  • filter重构
var arr = [1, 2,, 2, 4, 3, 4, 5, 4, 2, 6, 2, 7];
function filter(arr,fn){
    var array=[];
    for(var i=0;i<arr.length;i++){
        if(fn(arr[i],i,arr)) array[array.length]=arr[i];
    }
    return array;
}
var arr1=filter(arr,function(item,index,a){
    return item>4;
});
console.log(arr1);  //(3) [5, 6, 7]
  • 应用示例
var data = [ //对象型数组(复杂型数组)
    { id: 1001, icon: "img/1.png", name: "餐饮0", num: 1, price: 10 },
    { id: 1002, icon: "img/2.png", name: "餐饮1", num: 1, price: 20 },
    { id: 1003, icon: "img/3.png", name: "餐饮2", num: 1, price: 30 },
    { id: 1004, icon: "img/4.png", name: "餐饮3", num: 1, price: 40 },
    { id: 1005, icon: "img/5.png", name: "餐饮4", num: 1, price: 50 },
    { id: 1006, icon: "img/6.png", name: "餐饮5", num: 1, price: 60 },
    { id: 1007, icon: "img/7.png", name: "餐饮6", num: 1, price: 70 },
    { id: 1008, icon: "img/8.png", name: "餐饮7", num: 1, price: 80 },
    { id: 1009, icon: "img/9.png", name: "餐饮8", num: 1, price: 90 },
    { id: 1010, icon: "img/10.png", name: "餐饮9", num: 1, price: 100 }
];
var arr1=data.filter(function(item,index,arr){
    return item.id===1006;
})
console.log(arr1); //返回数组[{…}],内容是 {id: 1006, icon: "img/6.png", name: "餐饮5", num: 1, price: 60}

16、reduce() 归并

  • 简介:
    arr.reduce(function(上次归并值,本次遍历的元素,索引值,数组),初始化值);
    如果没有设置初始化值,上次归并值初始值为数组的第0项,本次遍历将从下标1开始;
    如果设置了初始化值,上次归并值初始值就是初始化值,本次遍历将从下标0开始。
var arr=[1,2,3,4,5];
var sum=arr.reduce(function(value,item,index,arr){
    console.log(value,item,index); //每次计算完成后三者的值
    return value+item; //返回到value,value是上次归并值
},100);
console.log(sum); //可以计算最后return的值 115
  • reduc重构
var arr=[1,2,3,4,5];
function reduce(arr,fn,initValue){//initValue 代表初始值
    var start=0; //代表遍历开始下标
    //如果没有设置初始值,上次归并值为arr[0],本次遍历从arr[1]的下标1开始
    if(initValue===undefined){
        initValue=arr[0];
        start++;
    }
    //否则,上次归并值为初始值,遍历从下标0开始,本次归并的结果给initValue
    for(var i=start;i<arr.length;i++){
        initValue=fn(initValue,arr[i],i,arr);
    }
    return initValue;
}
var sum=reduce(arr,function(value,item,index,a){
    return value+item;
},100);
console.log(sum); //115
  • reduce常用应用:
    1、求总价;
    2、把很多符合条件的结果归并起来;
    3、reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值,就如上面那段程序所实现的功能;
    4、reduce() 可以作为一个高阶函数,用于函数的 compose;
  • 注意: reduce() 对于空数组是不会执行回调函数的(不检测空元素,跳过空元素)。
  • 应用示例
var data = [
    { id: 1001, icon: "img/1.png", name: "餐饮0", num: 1, price: 10 },
    { id: 1002, icon: "img/2.png", name: "餐饮1", num: 1, price: 20 },
    { id: 1003, icon: "img/3.png", name: "餐饮2", num: 1, price: 30 },
    { id: 1004, icon: "img/4.png", name: "餐饮3", num: 1, price: 40 },
    { id: 1005, icon: "img/5.png", name: "餐饮4", num: 1, price: 50 },
    { id: 100, icon: "img/6.png", name: "餐饮5", num: 1, price: 60 },
    { id: 1007, icon: "img/7.png", name: "餐饮6", num: 1, price: 70 },
    { id: 1008, icon: "img/8.png", name: "餐饮7", num: 1, price: 80 },
    { id: 1009, icon: "img/9.png", name: "餐饮8", num: 1, price: 90 },
    { id: 1010, icon: "img/10.png", name: "餐饮9", num: 1, price: 100 }
];

1、模拟购物车计算价格总和
//给每个元素增加一个selected属性;
//通过Math.random() < 0.5来确定selected是否为选中状态;
//然后固定数量num不超过10;
//把该商品的总价格算出来;
data.forEach(function (item) {
    item.selected = Math.random() < 0.5;
    item.num = parseInt(Math.random() * 5 + 5);
    item.total = item.num * item.price;
    // console.log(item.selected,item.num,item.total); //自己打印试试
});
//将所有被选中的商品价格总值加起来,计算总总价格后给value
var sum = data.reduce(function (value, item) {
    return item.selected ? value + item.total : value;
}, 0);
console.log(sum);

2、如果找到返回该id===1006的,否则返回归并值
// var item = data.reduce(function (value, item) {
//     return item.id == 1006 ? item : value;
// }, null);
// console.log(item); //没找到,返回null

17、reverse()倒序

  • 倒序,翻转数组,不排序,改变原数组,并返回返回原数组。
var arr=[1,4,6,2,3,8,7,6,5,3,9];
console.log(arr.reverse(),arr); //结果都是(11) [9, 3, 5, 6, 7, 8, 3, 2, 6, 4, 1] 
//不排序,因此与数组元素值无关
var arr=["a","b","c","d"];
console.log(arr.reverse()); //(4) ["d", "c", "b", "a"]   
  • reverse重构
1、第一种方法
//重构思想:从中间对半劈开,以temp为介质,把前后元素位置交换
var arr=[1,4,,"c","d",3,9];
function reverse(arr){
    var len=parseInt(arr.length/2); //交换次数
    for(var i=0;i<len;i++){
        var temp=arr[arr.length-1-i];
        arr[arr.length-1-i]=arr[i];
        arr[i]=temp;
    }
    return arr;
}
console.log(reverse(arr)); //(7) [9, 3, "d", "c", undefined, 4, 1]

2、重构第二种方法
//重构思路:新创建一个数组arr1,然后把原数组arr的值颠倒到新数组arr1里;
//最后再把新数组arr1的元素重新赋值给原数组arr,函数执行完毕,局部变量arr1销毁
var arr=[0,4,,"c","d",3,0];
function reverse1(arr){
    var array=[];
    var index=0;
    for(var i=arr.length-1;i>=0;i--){
        array[index++]=arr[i];
    }
    arr=array.splice(0);
    return arr;
}
console.log(reverse1(arr)); //(7) [0, 3, "d", "c", undefined, 4, 0]

18、sort() 排序(正序(默认)/倒序/乱序)

1、直接排序,只能按元素值的第一个数字进行排序
var arr=[1,4,6,3,9,10,100];
arr.sort();
console.log(arr);  //(7) [1, 10, 100, 3, 4, 6, 9] 有问题哦

2、正序排列
arr.sort(function(a,b){
    return a-b; 
})
console.log(arr);  //(7) [1, 3, 4, 6, 9, 10, 100]

3、倒序排列
arr.sort(function(a,b){
    return b-a; 
})
console.log(arr);  //(7) [100, 10, 9, 6, 4, 3, 1]

4、乱序排列,每次排列结果不一样
var arr=[];
for(var i=0;i<100;i++){
    arr.push(i); //给arr添加0~99的元素
}
//乱序排列
var i=-1;
arr.sort(function(){
    return Math.random()-0.5; //乱的比较彻底
})
console.log(arr); //0~99的数字乱序打印出来

19、flatMap

  • 遍历,将二维数组扁平化;
  • 不改变原数组;
  • 返回一个新数组。
var arr1=[[1,2,0,,3],[4,5,6],7,8,"s",,9];
var arr2=arr1.flatMap(function(item,index,a){//用arr2接收返回的新数组
	//console.log(item,index); //打印一下看看
    return item;
});
console.log(arr2,arr1); 
//arr2: [1, 2, 0, 3, 4, 5, 6, 7, 8, "s", 9]
//arr1:[Array(5), Array(3), 7, 8, "s", empty, 9]

三种常见排序

  • 冒泡排序、选择排序、快速排序

1、冒泡

/*
	冒泡排序:
	1、从后向前循环;
	2、内部从前向后循环到外层变量;
	3、判断前值是否大于后值,若大于,则交换。
*/
var arr=[1,4,2,2,3,10];
function bubblingSort(arr){
    var len=arr.length;
    while(len>0){
        for(var i=0;i<len;i++){
            if(arr[i]>arr[i+1]){
                var temp=arr[i];
                arr[i]=arr[i+1];    
                arr[i+1]=temp;
            }
        }
        len--;
    }
}
bubblingSort(arr);
console.log(arr); //(6) [1, 2, 2, 3, 4, 10]

2、选择排序

/*
	选择排序
	思路:先找出最小或者最大的索引值,然后用当前的下标的元素与这个最小的元素交换。
	1、遍历数组;
	2、设置最小的索引值为当前的索引值;
	3、从当前的下一项开始遍历到数组的尾部;
	4、判断所有遍历的值中最小的值得索引值;
	5、交换当前值和最小索引值的元素。
*/
function indexSort(arr){
    var minIndex;
    var len=arr.length;
    for(var i=0;i<len;i++){
        minIndex=i;
        for(var j=i+1;j<len;j++){
            minIndex=arr[minIndex]<arr[j]?minIndex:j;
        }
        var temp=arr[i];
        arr[i]=arr[minIndex];
        arr[minIndex]=temp;
    }
}
var arr=[1,4,2,2,3,10];
indexSort(arr);
console.log(arr); //(6) [1, 2, 2, 3, 4, 10]

3、快速排序

/*
	快排(快速排序)
	1、删除数组中间的元素,并且,将这个元素返回一个变量;
	2、创建两个空数组,一个是left,一个是right,遍历这个数组,
	   将小于中间元素的数据存入left,大于中间元素的数据存入right;
	3、将left数组递归与中间元素和right数组递归的结果合并返回;
	4、在函数最顶部,一定要写数组长度小于等于1,返回该数组。
	
	注意:要重新赋值给元素组替换。
*/
function quickSort(arr){
    if(arr.length<=1) return arr;
    var left=[];
    var right=[];
    //因为splice返回的是被删除元素组成的数组,哪怕只有一个元素,也得把它提取出来
    var item=arr.splice(parseInt(arr.length/2),1)[0];
    for(var i=0;i<arr.length;i++){
        if(arr[i]<item) left.push(arr[i]);
        else right.push(arr[i]);
    }
    var arr1=quickSort(left).concat(item,quickSort(right)); //递归
    return arr1;
}
var arr=[1,4,2,2,3,10];
arr=quickSort(arr); //重新赋值替换原数组
console.log(arr);  //(6) [1, 2, 2, 3, 4, 10]

非数组列表转化为数组

  • 几种不同方法:
var inputs=document.getElementsByTagName("input");
console.log(inputs); //HTMLCollection(10)
把他转换成数组的几种方法:
ES6
var list=Array.from(inputs);
console.log(list);  //Array(10)

ES5
var list=Array.prototype.slice.call(inputs);
var list=[].slice.call(inputs);
var list=Array.prototype.concat.apply([],inputs);
var list=[].concat.apply([],inputs);
  • 示例:
<p>
    功能介绍:
    按第一个全选按钮,所有选框同时选中或解除选中;
    单按下面的选框,只要有未选中的,全选按钮就为未选中状态。
</p>
<ul>
    <li><input type="checkbox">全选</li>
    <li><input type="checkbox"></li>
    <li><input type="checkbox"></li>
    <li><input type="checkbox"></li>
    <li><input type="checkbox"></li>
    <li><input type="checkbox"></li>
    <li><input type="checkbox"></li>
    <li><input type="checkbox"></li>
    <li><input type="checkbox"></li>
    <li><input type="checkbox"></li>
</ul>
var inputs = document.getElementsByTagName("input");
var arr = Array.from(inputs); //转换成数组
for(var i=0;i<arr.length;i++){
    arr[i].onclick=clickHandler; //给每个input添加点击事件
}
function clickHandler(){
    var self=this;
    if(arr.indexOf(this)===0){//如果按第一个全选按钮
        arr.forEach(function(item,index){
            if(index===0) return; //不检测第一个全选按钮
            //用self而非this,是因为forEach中的this被重新指向到window(所有的回调函数中也有这一特点),万恶的this
            item.checked=self.checked;
            //其余选框的状态跟随全选按钮的状态
        })
    }else{//如果按其他普通按钮
        arr[0].checked=arr.slice(1).every(function(item){
            return item.checked;
            //如果所有的普通按钮都被选中了,都为true,那么全选按钮为选中状态;
            //反之,只要有一个选框未选中为false,全选按钮就为未选中false
        })
    }
}

复杂型数组

二维数组和多维数组

  • 行列唯一对应值(完成格状物的操作)。
//二维数组
var arr0 = [];//先定义一个数组
for (var i = 0; i < 10; i++) {
    arr0[i] = [];//第二层数组
    for (var j = 0; j < 20; j++) {
        arr0[i][j] = i * 10 + j;//二维数组赋值
    }
}
console.log(arr0);//行列有唯一对应值
  • 二维数组扁平化,flatMap,不检测空元素
1、当数组元素类型统一
var arr=[[1,2,3],[4,5,6],7,8,9];
var arr1=arr.flatMap(function(item,index,a){
    return item;
})
console.log(arr1); //(9) [1, 2, 3, 4, 5, 6, 7, 8, 9]
2、当数组元素类型不统一
var arr=[[1,2,0,,3],[4,5,6],7,8,"s",,9];
//用flatMap将上面的数组扁平化结果为[1, 2, 0, 3, 4, 5, 6, 7, 8, "s", 9];

对象型数组

//对象型数组
var kk={ id: 1005, icon: "img/5.png", name: "餐饮4", num: 1, price: 50 };
var data = [//定义对象数组,每个元素都是一个对象
    { id: 1001, icon: "img/1.png", name: "餐饮0", num: 1, price: 10 },
    { id: 1002, icon: "img/2.png", name: "餐饮1", num: 1, price: 20 },
    { id: 1003, icon: "img/3.png", name: "餐饮2", num: 1, price: 30 },
    { id: 1004, icon: "img/4.png", name: "餐饮3", num: 1, price: 40 },
    kk,
    { id: 1006, icon: "img/6.png", name: "餐饮5", num: 1, price: 60 },
    { id: 1007, icon: "img/7.png", name: "餐饮6", num: 1, price: 70 },
    { id: 1008, icon: "img/8.png", name: "餐饮7", num: 1, price: 80 },
    { id: 1009, icon: "img/9.png", name: "餐饮8", num: 1, price: 90 },
    { id: 1010, icon: "img/10.png", name: "餐饮9", num: 1, price: 100 }
];
//错误用法
var obj={ id: 1005, icon: "img/5.png", name: "餐饮4", num: 1, price: 50 };
console.log(data.indexOf(obj));//-1 不能找到对象元素的索引,因为这个的引用地址,与上面的引用地址是不一样的
//正确用法
console.log(data.indexOf(kk));//4 
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!