JS数组必备知识

所有内容均不是原创,单纯之前学习时做的笔记。内容结合了非常多的文章视频,很多已经记不清参考的哪里了,所以就不加参考说明了。

数组常用的方法

push:在数组末尾插入元素

  • 在数组的末尾添加一个或多个元素,并返回数组的新长度。
  • let arr = [1,2,3,4,5]
    var longth = arr.push(6,7);
    console.log(arr, longth);
    

unshift:在数组的头部插入元素

  • 在数组的头部添加一个或多个元素,并返回数组的新长度
  • let arr = [1,2,3,4,5]
    var length = arr.unshift(0);
    console.log(arr,length);//[0,1,2,3,4,5] 6
    

pop:删除数组末尾的元素

  • 删除索引值最大的元素,并返回被删除的元素。
  • let arr = [1,2,3,4,5]
    var delElement = arr.pop();
    console.log(arr, delElement); //[1,2,3,4] 5
    

shift:删除数组的头部元素

  • 删除索引为0的元素,并返回删除的元素
  • let arr = [1,2,3,4,5]
    var delElement = arr.shift();
    console.log(arr, delElement); //[2,3,4,5] 1
    

splice:在数组中添加删除或替换元素

  • 在任意位置添加或删除元素,返回删除或被替换的值,如果没有被删除或替换则返回空数组;splice()方法会修改原数组的值;

    1. 只有一个值时,从当前位置删除到数组末尾

      let arr=[1,2,3,4,5];
      let num1=arr.splice(1);
      console.log(num1,arr);//[2,3,4,5] arr=[1]
      
    2. 有两个值时,第一个值为删除的位置,第二个值为删除的个数;

      let arr=[1,2,3,4,5];
      let num1=arr.splice(2,3);
      //删除从索引值2开始的3个元素
      console.log(num1,arr);// [3,4,5] [1,2]
      
    3. 有三个或者多个值时,第一个值为插入元素的位置,第二个值为替换的个数,后面的值都为插入的新元素;

      let arr=[1,2,3,4,5];
      let num2=arr.splice(2,1,6,7,8);
      //从索引值2开始替换掉1个元素,并且插入6,7,8
      //如果第二个值为0,则不替换,直接插入6,7,8;
      console.log(num2,arr);//[3] [1,2,6,7,8,4,5]
      
    4. 允许负向索引

      let arr = [1, 2, 5];
      // 从索引 -1(尾端前一位)
      // 删除 0 个元素,
      // 然后插入 3 和 4
      arr.splice(-1, 0, 3, 4);
      alert( arr ); // 1,2,3,4,5
      

sort:将数组进行排序

  • 将数组进行排序(升序),返回新数组,原数组也会改变;

  • sort是按照Ascii码来排列的

  • sort里面传函数的话,根据返回值来排列

    • 负值,第一个参数排在前面
    • 正值,第一个参数排在后面
    • 0,保持不动
  • let arr = [2,3,5,1,4];
    //升序
    let newArr1 = arr.sort((a,b)=>{
        return a-b
    })
    console.log(newArr1,arr);//[1,2,3,4,5] [1,2,3,4,5]//倒序
    let newArr2 = arr.sort((a,b)=>{
        return b-a
    })
    console.log(newArr2,arr);//[5, 4, 3, 2, 1] [5, 4, 3, 2, 1]/*return -1; a排列在b前面
      return 1; b排列在a 前面
      return 0; a,b的位置不变
    */
    

reverse:将数组进行倒序

  • 可以将原数组进行倒序,并返回改变后的数组;
  • let arr=[1,2,3,4,5];
    let newArr=arr.reverse();
    console.log(newArr,arr);//newArr=[5,4,3,2,1] [5,4,3,2,1];
    

concat:数组和数组(或元素)的合并

  • 合并数组或元素,返回新的数组,原数组不会改变

  • let arr = [1,2,3,4,5];
    let newArr = arr.concat([6,7,8],9,10);
    console.log(newArr,arr);//[1,2,3,4,5,6,7,8,9,10] [1,2,3,4,5]
    
  • 通常只合并数组中的元素。其他对象,即使它们看起来像数组一样,但仍然会被作为一个整体添加。但是,如果类似数组的对象具有 Symbol.isConcatSpreadable 属性,那么它就会被 concat 当作一个数组来处理:

    let arr = [1, 2];
    ​
    let arrayLike = {
      0: "something",
      length: 1
    };
    ​
    let arrayLike1 = {
      0: "something",
      1: "else",
      [Symbol.isConcatSpreadable]: true,
      length: 2
    };
    console.log( arr.concat(arrayLike) ); // [1,2,{0: "something",length: 1}]
    console.log( arr.concat(arrayLike1) ); // [1, 2, 'something', 'else']
    

slice:截取复制数组指定位置的内容

  • slice(开始位置,结束位置);第二个参数不写默认到尾部,只能从前往后截取;返回的值为截取到的内容形成的新数组;

  • let copyArr=arr.slice();
    // slice()或者slice(0)都可以复制数组;
    let arr=[1,2,3,4,5];
    let newArr=arr.slice(1,3);
    //截取索引1到索引3(不包括3)的值;
    console.log(newArr,arr);//[2,3] [1,2,3,4,5]
    console.log( arr.slice(-2) ); // [4,5](复制从位置 -2 到尾端的元素)
    

join:指定字符连接字符串

  • 数组的每个元素以指定的字符连接形成新字符串返回;
  • 经常会跟split搭配使用
  • let arr=[1,2,3,4,5];
    let newArr=arr.join();
    //默认用逗号连接
    console.log(newArr);//1,2,3,4,5;
    //如果连接符为空字符串,则会无缝连接
    console.log(arr.join(""));//输出为12345;
    

总结

push、unshift、pop、shift、splice、sort、reverse会改变原数组,concat、slice、join不会改变原数组。

方法说明
slice()获取数组中的某段数组元素
unshift()在数组开头添加元素
push()在数组末尾添加元素
shift()删除数组中第一个元素
pop()删除数组最后一个元素
toString()将数组转换为字符串
join()将数组元素连接成字符串
concat()多个数组连接为字符串
sort()数组元素正向排序
reverse()数组元素反向排序

数组遍历

数组常见遍历方法:forEach、map、filter、find、every、some、reduce,它们有个共同点:不会改变原始数组。

preview

以上方法,除了for循环之外,均含有三个参数

1.当前正在遍历的元素 2.当前的索引 3.当前遍历的数组

传统方法 for循环

  • for…infor...of的主要区别在于他们的迭代方式

    • 推荐在循环对象属性的时候,使用for…in,在遍历数组的时候推荐使用for…of
    • for…in 循环出来的是key, for…of循环出来的是value
    • for…in 是ES5 标准,for …of 是ES6标准,兼容性可能存在些问题,请注意使用
    • for…of 不能遍历普通的对象,需要和Object.keys() 搭配使用
  • var arr = ['2', '小明', true, 'HelloWorld'];
    for (var i = 0; i < arr.length; i++) {
        console.log(arr[i])
    }
    /*
        1、for循环不到数组的私有属性
        2、可以使用return|break|continue终止|结束循环
        3、for属于编程式写法
    */
    
  • var arr = ["first","second",'third' ,"fourth"];
    for(var i in arr){
      console.log(arr[i] +'/' + i);
        /*输出结果为:
            first/0
            second/1
            third/2
            fourth/3
        */
    }
    /*
        1、可以遍历到数组私有属性的值
        2、i的类型是string型
        3、可以使用return|break|continue终止|结束循环
        4、不返回新数组
        5、可以遍历对象,遍历对象时key编程对象的属性名
    */
    
  • var arr = ["first","second",'third' ,"fourth"];
    for(var item of arr){
      console.log(item);
        /*输出结果:
            first
            second
            third
            fourth
        */
    }
    /*
      1、不可以遍历数组的私有属性的值
        2、item的值就是arr项的值
        3、可以使用return|break|continue终止|结束循环
        4、不返回新数组
    */
    

forEach:遍历数组

  • var arr = [1, 2, 3];
    arr.forEach(function(ele, index) {
      console.log(index + ":" + ele);//0:1 1:2 2:3
    })
    /*
        1、forEach循环不到数组的私有属性
        2、return|break|continue不起作用
        3、forEach属于声明式写法,不关心具体实现
        4、循环数组中每一个元素并采取操作,可以不用知道数组长度
        5、返回值:无
    */
    

map:将数组映射成另一个数组

  • map通过指定函数处理数组的每个元素,并返回处理后新的数组,map不会改变原始数组。
  • forEachmap的区别在于,forEach没有返回值。
  • map需要返回值,如果不给return,默认返回undefined
  • 方法名filtermap
    是否操作原数组不会不会
    返回结果过滤后的新数组新数组
    回调函数的返回结果如果返回true这一项放到新数组中回调函数中返回什么这一项就是什么

filter:从数组中找出所有符合指定条件的元素

  • filter 检测数值元素,并返回符合条件所有元素的数组。 filter 不会改变原始数组。
  • //filter遍历数组
    //主要用于筛选
    //返回值 筛选之后的一个新数组
    var arr = [1, 2, 4, 5,0 ];
    var n = arr.filter(function(ele, index) {
      return ele > 3;
    })
    console.log(n);// [4, 5]
    

every&some(some: 一真即真;every: 一假即假)

  • every:数组中是否每个元素都满足指定的条件

    //every遍历数组
    //遍历数组中是否“每个”元素都符合条件
    //返回Boolean值
    var arr = [1, 3, '小明', true, 'HelloWorld'];
    var newstate = arr.every(function(ele) {
      return typeof ele == 'number'
    })
    console.log(newstate);//false
    
  • some:数组中是否有元素满足指定的条件

    // 遍历数组中是否有符合条件的元素
    // 返回值:boolean
    var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, ];
    var result = arr.some(function(ele, i) {
      if (ele > 3) {
        return true;
      }
    })
    console.log(result);//true
    

reduce:将数组合成一个值

  • 接收一个方法作为累加器,数组中的每个值(从左至右) 开始合并,最终为一个值。

在数组中搜索

indexOf/lastIndexOf 和 includes

arr.indexOfarr.lastIndexOfarr.includes 方法与字符串操作具有相同的语法,并且作用基本上也与字符串的方法相同,只不过这里是对数组元素而不是字符进行操作:

  • arr.indexOf(item, from) 从索引 from 开始搜索 item,如果找到则返回索引,否则返回 -1
  • arr.lastIndexOf(item, from) —— 和上面相同,只是从右向左搜索。
  • arr.includes(item, from) —— 从索引 from 开始搜索 item,如果找到则返回 true(译注:如果没找到,则返回 false)。
  • 请注意,这些方法使用的是严格相等 === 比较。所以如果我们搜索 false,会精确到的确是 false 而不是数字 0。如果我们想检查是否包含某个元素,并且不想知道确切的索引,那么 arr.includes 是首选。此外,includes 的一个非常小的差别是它能正确处理NaN,而不像 indexOf/lastIndexOf
  • let arr = [1, 0, false];
    ​
    alert( arr.indexOf(0) ); // 1
    alert( arr.indexOf(false) ); // 2
    alert( arr.indexOf(null) ); // -1alert( arr.includes(1) ); // trueconst arr = [NaN];
    alert( arr.indexOf(NaN) ); // -1(应该为 0,但是严格相等 === equality 对 NaN 无效)
    alert( arr.includes(NaN) );// true(这个结果是对的)
    

find 和 findIndex

  • arr.find回调函数中返回true停止循环并返回那一项的值,未找到返回undefined

    let result = arr.find(function(item, index, array) {
      // 如果返回 true,则返回 item 并停止迭代
      // 对于假值(false)的情况,则返回 undefined
    });
    ​
    let users = [
      {id: 1, name: "John"},
      {id: 2, name: "Pete"},
      {id: 3, name: "Mary"}
    ];
    let user = users.find(item => item.id == 1);
    alert(user.name); // John
    
  • arr.findIndex方法(与 arr.find 方法)基本上是一样的,但它返回找到元素的索引,而不是元素本身。并且在未找到任何内容时返回 -1

数组去重

数组去重(同一基本类型)

使用Set + Array.from、set + 解构赋值去重

  • ES6中新增了数据类型set,set的一个最大的特点就是数据不重复。Set函数可以接受一个数组(或类数组对象)作为参数来初始化,利用该特性也能做到给数组去重。
  • Array.from方法可以将Set结构转换为数组结果,而我们知道set结果是不重复的数据集,因此能够达到去重的目的。
  • function unique(arr) {
        //1、return Array.from(new Set(arr))
        //2、return [...new Set(arr)]
    }
    

使用Array.filter + Array.indexOf

  • arr.filter((item, index, arr) => {
      return arr.indexOf(item) === index;
      //indexOf只会返回第一个符合的值的索引
    }),
    

使用Array.reduce + Array.includes

  • arr.reduce((cur,next) => {
        return cur.includes(next) ? cur : [...cur,next]
    },[])
    

使用forEach+indexOf

  • function uniqueArr (array) {
      var _arr = []:
      array. forEach(function (item) {
      if (_arr. index0f(item)===-1)
          _arr.push(item):
      });
      return _arr;
    }
    

数组对象去重

  • 顾名思义,数组里面的项不再是基本类型,在实际业务开发场景中,我们需要根据对象指定的属性去除重复的项。

for...of + Object

  • 首先创建一个空对象,然后用 for 循环遍历
  • 利用对象的属性不会重复这一特性,校验数组元素是否重复
  • function distinct(arr,key) {
        const obj = {}
        for (let i of arr) {
            obj[i[key]] = i
        }
        return Object.values(obj);
    }
    

利用Map的键不可重复

  • const uniqBy = (arr,key) => {
      return [...new Map(arr.map(item => [item[key],item])).values()];
    }
    

类数组

  • 类数组是类似于数组的对象,有数组的下标,跟length属性
  • var obj = {
        '2': 3,
        '3': 4,
        'length': 2,
        'splice': Array.prototype.splice,
        'push': Array.prototype.push,
    }
    obj.push(1);
    obj.push(2);
    console.log(obj); // [empty × 2, 1, 2, splice: ƒ, push: ƒ]//push原理
    Array.prototype.push = function (elem){
      this[thi  s.length] = elem;
      this.length++;
    }