详谈 JavaScript 数组操作

作者: VoyagerOne | 来源:发表于2017-12-21 00:54 被阅读76次

    前言

    在前端开发的时候,冷不丁地会遇到对数组的赋值、合并、增改等操作,由于方法有点多,本人往往临时查阅,现在想做一个Js数组操作的集合,也是巩固一下这个时常遇到的知识。

    创建数组

    使用关键字 new

    使用关键词 new 即可一个创建数组对象:

    //数组在Js中亦为object
    let myArray = new Array();
    console.log(typeOf(myArray)); //object 
    myArray[0] = "Eric";
    myArray[1] = "Jessica";
    myArray[3] = "Lucy"; //给数组前3项赋值
    

    也可以在构造时传入数组长度:

    let myArray = new Array(20);
    console.log(myArray.length); //20 此时创建了一个长度为20的数组myArray
    console.log(myArray[0]); //undefined 此时20个位置为undefined
    myArray[0] = "Eric"; //为第一个元素赋值,此时数组其他元素保持为undefined
    

    也可以在构造时直接传入数组元素:

    let myArray = new Array("Eric","Jessica","Lucy");
    console.log(myArray[1]); //Jessica
    
    字面量方式

    使用字面量方式可以较为直观的创建数组:

    //创建一个空数组
    let myArray = [];
    console.log(myArray.length); //0 
    //字面量赋值
    let myArray = ["Eric","Jessica","Lucy"];
    console.log(myArray[1]); //Jessica
    
    创建二维数组

    由于Js没有矩阵,但是由于数组元素可为所有数据类型,所以可以用数组嵌套的方式创建二维数组:

    let myArray = [];
    myArray[0] = [1,2,3,4];
    myArray[1] = [4,3,2,1];
    console.log(myArray[1][0]); //4
    

    首尾增删

    删除数组末项元素Array.prototype.pop()
    // 此方法会修改原数组
    let myArray = new Array("Eric","Jessica","Lucy");
    myArray.pop();
    console.log(myArray); // [ 'Eric', 'Jessica' ]
    
    向数组末尾添加新元素Array.prototype.push(elem1,elem2,...)
    // 此方法会修改原数组
    let myArray = new Array("Eric","Jessica","Lucy");
    myArray.push("Kevin");
    console.log(myArray); //[ 'Eric', 'Jessica', 'Lucy', 'Kevin' ]
    // 也可以一次追加多个元素
    myArray.push("Bob","Mike","Tom");
    console.log(myArray); // [ 'Eric', 'Jessica', 'Lucy', 'Kevin', 'Bob', 'Mike', 'Tom' ]
    

    是的 push()pop() 便可以模拟一个栈。

    删除数组首项元素Array.prototype.shift():
    // 此方法会修改原数组
    let myArray = new Array("Eric","Jessica","Lucy");
    myArray.shift();
    console.log(myArray); // [ 'Jessica', 'Lucy' ]
    
    向数组首部添加新元素Array.prototype.unshift(elem1,elem2,...):
    // 此方法会修改原数组
    let myArray = new Array("Eric","Jessica","Lucy");
    myArray.unshift("Tom");
    console.log(myArray); // [ 'Tom', 'Eric', 'Jessica', 'Lucy' ]
    // 也可一次向首部加多个新元素
    myArray.unshift("Bob","Kevin");
    console.log(myArray); // [ 'Bob', 'Kevin', 'Tom', 'Eric', 'Jessica', 'Lucy' ]
    

    任意位置增删Array.prototype.splice()

    删除任意位置的元素

    虽然可以让数组某元素赋值为undefined,但是这样其仍然会占据一个位置,我们可以使用Array.prototype.splice(start,nums)来删除数组中某一位置的元素:

    // splice()方法会修改原数组
    let myArray = [ 'Bob', 'Kevin', 'Tom', 'Eric', 'Jessica', 'Lucy' ];
    
    // 从索引0开始,删除1个元素
    myArray.splice(0,1);
    console.log(myArray); // [ 'Kevin', 'Tom', 'Eric', 'Jessica', 'Lucy' ]
    
    // 从索引2开始,删除1个元素
    myArray.splice(2,1);
    console.log(myArray); // [ 'Kevin', 'Tom', 'Jessica', 'Lucy' ]
    
    // 从索引0开始,删除2个元素
    myArray.splice(0,2);
    console.log(myArray); // [ 'Jessica', 'Lucy' ]
    
    // 若不指定第二个 nums 参数,则将删除 (myArray.length - start) 个元素
    // 若 nums 值大于剩下的元素数量,则删除 start 位置(含)后的所有元素
    let myArray = [ 'Bob', 'Kevin', 'Tom', 'Eric', 'Jessica', 'Lucy' ];
    
    // 从索引2开始,删除 6 - 2 个元素,因为4>3,所以删除[2](含)后所有元素
    myArray.splice(2);
    console.log(myArray); // [ 'Bob', 'Kevin' ]
    
    在任意位置增加元素

    这里我们仍然使用Array.prototype.splice(),不过将为其加入第三类参数:Array.prototype.splice(start,nums,elem1,elem2...)

    let myArray = [ 'Bob', 'Kevin', 'Tom', 'Eric', 'Jessica', 'Lucy' ];
    
    // 从索引0开始,删除0个元素,增加1个元素
    myArray.splice(0,0,"Gave");
    console.log(myArray); // [ 'Gave', 'Bob', 'Kevin', 'Tom', 'Eric', 'Jessica', 'Lucy' ]
    
    // 从索引1开始,删除2个元素,增加1个元素
    myArray.splice(1,2,"Kelly"); // [ 'Gave', 'Kelly', 'Tom', 'Eric', 'Jessica', 'Lucy' ]
    

    分割数组

    分割数组会用到两个方法,splice() 直接对数组产生作用,slice()则不改变愿数组。

    分割并修改原数组Array.prototype.splice()

    上文提到的splice()其实还有个返回值,那就是被分割出来的元素所构成的数组:

    // splice()方法会修改原数组
    let myArray = [ 'Bob', 'Kevin', 'Tom', 'Eric', 'Jessica', 'Lucy' ];
    
    // 从索引1开始,删除2个元素
    let mySplicedArray = myArray.splice(1,2);
    console.log(mySplicedArray); // [ 'Kevin', 'Tom' ]
    console.log(myArray); // [ 'Bob', 'Eric', 'Jessica', 'Lucy' ]
    
    分割不修改原数组Array.prototype.slice()

    Array.prototype.slice(begin,end) 会返回一个从 begin 到 end (不包括end)位置上的元素所组成的数组,并不修改原数组。

    // slice()方法不会修改原数组
    let myArray = [ 'Bob', 'Kevin', 'Tom', 'Eric', 'Jessica', 'Lucy' ];
    
    //从索引1开始,分出一个到索引2的数组
    let mySplicedArray = myArray.slice(1,3);
    console.log(mySplicedArray); // [ 'Kevin', 'Tom' ]
    console.log(myArray); // [ 'Bob', 'Kevin', 'Tom', 'Eric', 'Jessica', 'Lucy' ]
    
    

    合并数组

    合并多个数组Array.prototype.concat()

    concat()可以合并两个或多个数组,返回一个合并后的数组,但不改变原数组.

    // 此方法不会改变原数组
    let myArray1 = [ 'Bob', 'Kevin', 'Tom' ];
    let myArray2 = [ 'Eric', 'Jessica', 'Lucy' ];
    let myArray3 = myArray1.concat(myArray2);
    console.log(myArray3); // [ 'Bob', 'Kevin', 'Tom', 'Eric', 'Jessica', 'Lucy' ]
    console.log(myArray1); // [ 'Bob', 'Kevin', 'Tom' ]
    console.log(myArray2); // [ 'Eric', 'Jessica', 'Lucy' ]
    
    // 合并多个数组
    let myArray1 = [ 'Bob', 'Kevin', 'Tom' ];
    let myArray2 = [ 'Eric', 'Jessica', 'Lucy' ];
    let myArray3 = [ 'Kelly', 'Kent' ];
    let myArray4 = myArray1.concat(myArray2, myArray3);
    console.log(myArray4); // [ 'Bob', 'Kevin', 'Tom', 'Eric', 'Jessica', 'Lucy', 'Kelly', 'Kent' ]
    
    //也可以合并嵌套的数组
    let myArray1 = [ 'Bob', 'Kevin', 'Tom' ];
    let myArray2 = [ [ 'Eric', 'Jessica' ], 'Lucy' ];
    let myArray3 = myArray1.concat(myArray2);
    console.log(myArray3); // [ 'Bob', 'Kevin', 'Tom', [ 'Eric', 'Jessica' ], 'Lucy' ]
    

    检索数组

    检索数组元素并返回其值

    Array.prototype.find()可以使我们传入一个检索函数,并按此检索数组,返回第一个符合的素组元素的值,若没有则返回undefined。

    // 检索并返回偶数项的值
    let myArray = [ 1, 2, 3, 5, 7, 17 ];
    let result = myArray.find((elem) => {
      if (elem === 0 || elem%2 === 0){
        return elem;
      }
    });
    console.log(result); // 2
    
    // 若结果有多个项符合,也只返回第一个满足的项
    let myArray = [ 1, 2, 3, 4, 5, 6 ];
    console.log(myArray.find((elem) => {
      if (elem === 0 || elem%2 === 0){
        return elem;
      }
    })); // 2
    
    检索数组元素并返回其索引

    Array.prototype.findIndex()以使我们传入一个检索函数,并按此检索数组,返回第一个符合的素组元素的索引,若没有则返回 -1。

    let myArray = [ 1, 2, 3, 5, 7, 17, 6 ];
    let result = myArray.findIndex((elem) => {
      if (elem === 0 || elem%2 === 0){
        return elem;
      }
    });
    console.log(result); // 1
    
    let myArray = [ 1, 3, 5, 7, 9 ];
    let result = myArray.findIndex((elem) => {
      if (elem === 0 || elem%2 === 0){
        return elem;
      }
    });
    console.log(result); // -1
    
    检测数组中是否存在某值

    Array.prototype.includes()可以判断一个数组是否包含一个指定的值,若是,返回 true,不是则返回 false。

    let myArray = [ 1, 3, 5, 7, 9 ];
    if (myArray.includes(20)){
      console.log("Yes");
    }else{
      console.log("No");
    } // No
    
    测试数组中至少有一个通过函数检测

    Array.prototype.some()测试数组中是否至少有一个元素通过由提供的函数实现的测试,提供的函数中含三个参数:当前值,索引,当前数组。

    let myArray = [ 1, 3, 5, 7, 9, 20 ];
    const isBiggerThan10 = (value,index,array) => {
      return value > 10;
    }
    if (myArray.some(isBiggerThan10)){
      console.log("Yes");
    }else{
      console.log("No");
    } // Yes
    
    测试数组中全体通过函数检测

    Array.prototype.every()测试数组中的所有元素是否都通过了指定函数的测试。

    let myArray = [ 1, 3, 5, 7, 9, 20 ];
    const isBiggerThan10 = (value,index,array) => {
      return value > 10;
    }
    if (myArray.every(isBiggerThan10)){
      console.log("Yes");
    }else{
      console.log("No");
    } // No
    

    some()若探测到有一个为true则立刻返回true,而every()则探测到有一个false则返回false,必须全为true的情况下,才返回true
    Array.prototype.findIndex()Array.prototype.find()只能用于检测数组中有没有符合的项,而不能找出哪些项符合,若要如此则需要遍历数组。

    遍历数组

    JavaScript中遍历数组的方法各种各样,你当然可以用for循环来进行,这里讲的是其内置的遍历函数。

    遍历数组并对每个元素执行一次函数

    Array.prototype.forEach()遍历数组,并传入一个函数,为每个元素执行,函数中包括:当前值、索引、当前数组三个参数。

    // 打印数组中的索引->值
    let myArray = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
    myArray.forEach((value,index,array) => {
      console.log(index + "->" + value);
    }); 
    // 0->1
    // 1->2
    // 2->3
    // 3->4
    // 4->5
    // 5->6
    // 6->7
    // 7->8
    // 8->9
    // 9->10
    
    // 遍历数组并将所有偶数项追加到新的数组
    let myArray = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
    let result = [];
    myArray.forEach((value,index,array) => {
      if (value === 0 || value%2 === 0){
        result.push(value);
      }
    });
    console.log(result); // [ 2, 4, 6, 8, 10 ]
    
    // 你也可以对便利的数组进行修改操作
    // 删除数组中的偶数项
    let myArray = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
    myArray.forEach((value,index,array) => {
      if (value === 0 || value%2 === 0){
        array.splice(index,1);
      }
    });
    console.log(myArray); // [ 1, 3, 5, 7, 9 ]
    
    // 把数组中的偶数项都+1
    let myArray = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
    myArray.forEach((value,index,array) => {
      if (value === 0 || value%2 === 0){
        array[index] = value + 1;
      }
    });
    console.log(myArray); // [ 1, 3, 3, 5, 5, 7, 7, 9, 9, 11 ]
    
    遍历数组、执行函数并返回新数组

    Array.prototype.map()会返回一个新数组,其元素是该数组中的每个元素都调用一个提供的函数后返回的结果,接受参数也有当前值、索引、当前数组。
    注意:上文的forEach() 并不会返回值。

    // 得到原数组每个元素+1的结果,并不修改原数组
    let myArray = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
    let newArray =  myArray.map((value,index,array) => {
      return value + 1
    });
    console.log(newArray); // [ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ]
    console.log(myArray); // [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
    
    //给每个元素+1,并不修改原数组
    let myArray = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
    let newArray =  myArray.map((value,index,array) => {
      return value+1;
    });
    console.log(newArray); // [ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ]
    console.log(myArray); // [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
    
    // 因为传入了当前array,所以也可以修改原数组
    // 删除数组中的偶数项
    let myArray = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
    myArray.map((value,index,array) => {
      if (value === 0 || value%2 === 0){
        array.splice(index,1);
      }
    });
    console.log(myArray); // [ 1, 3, 5, 7, 9 ]
    
    遍历数组并过滤

    上文我们在删除数组中的偶数项时,用到了 splice(),相当于完成了过滤,而Js中提供了一个更简捷的写法Array.prototype.filter(),可以为其传入过滤函数,其参数亦有三个:当前值、索引,当前数组

    // 过滤掉数组中的质数,不改变原数组
    const isPrime = (num) => {
      if(typeof num !== "number" || !Number.isInteger(num)) {
        return false;
      }
      if(num === 2) {
        return true;
      } else if(num % 2 == 0) {
        return false;
      }
      let squareRoot = Math.sqrt(num)
      for(let i = 3; i <= squareRoot; i += 2) {
        if(num % i === 0) {
          return false;
        }
      }
      return true;
    }
    let myArray = [ 1, 7, 9, 13, 45, 113, 90, 89, 9, 17 ];
    let newArray = myArray.filter((value,index,array)=>{
      if (isPrime(value)){
        return false;
      }else{
        return true;
      }
    });
    console.log(newArray); // [ 9, 45, 90, 9 ]
    console.log(myArray); // [ 1, 7, 9, 13, 45, 113, 90, 89, 9, 17 ]
    

    数组排序

    排序算法千千万,这里只介绍Array.prototype.sort()中对比函数的使用。

    按字符Unicode编码来排序

    Array.prototype.sort()若不传比较函数,则默认按照Unicode编码来排序

    let myArray = [ 'a', 'b', 'k', 'm', 'c', 'z', 'l', 'N', 'B', 'q' ];
    myArray.sort();
    console.log(myArray); // [ 'B', 'N', 'a', 'b', 'c', 'k', 'l', 'm', 'q', 'z' ]
    
    let myArray = [ 1, 7, 9, 13, 45, 113, 90, 89, 9, 17 ];
    myArray.sort();
    console.log(myArray); // [ 1, 113, 13, 17, 45, 7, 89, 9, 9, 90 ]
    
    // 可见这样排序并不是我们希望的,使用场景少
    
    自定义排序

    Array.prototype.sort()中传入的比较函数compare(a, b),若返回值小于 0,则a在b之前;若返回值等于 0,则a,b位置不变;若返回值大于 0 ,则b在a之前。

    // 按照由小到大顺序排列
    const compare = (a, b) => {
      if (a>b){
        return 1
      }
      if (a===b){
        return 0
      }
      if (a<b){
        return -1
      }
    }
    let myArray = [ 1, 7, 9, 13, 45, 113, 90, 89, 9, 17 ];
    myArray.sort(compare);
    console.log(myArray); // [ 1, 7, 9, 9, 13, 17, 45, 89, 90, 113 ]
    

    其他操作(未完)

    相关文章

      网友评论

        本文标题:详谈 JavaScript 数组操作

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