JavaScript数组方法

168 阅读7分钟

数组方法

1、栈方法

js高级程序设计中说:栈是后进先出(last in first out)的一种数据结构,最近被添加的项目最先被删除,数据的插入和删除都发生在栈数据结构中的一端。例如:push和pop都发生在数组的尾端。直观点,栈可以想象成一个桶,我有a,b两个物品,依次放入桶中,a在b的下面,b是最后放入桶里的。那当我取物品的时候,首先取的应该是b,然后才是a。也就是后放入桶里的b,是最先被取出的。这就是后进先出。

  • push(...items) 尾部插入一项或多项

    const arr = [1, 2, 3];
    arr.push(4); // 4 返回数组长度, 数组末尾增加一项,[1, 2, 3, 4]
    
  • pop() 尾部删除一项

    arr.pop(); // 4 返回删除项
    

2、队列方法

与栈方法相反,队列方法的特点是先进先出(first in first out),在数据中的后面插入数据,在数据头部获得数据。也就是说,队列方法是在尾部添加数据,头部删除数据可以用push尾部插入,shift头部删除模拟队列方法。

  • shift(),头部删除一项

    const arr = [1, 2, 3];
    arr.shift(); // 1 返回删除项
    
  • unshift(...items),头部插入一项或者多项

    arr.unshift(1); // 3 返回数组长度
    

3、排序方法

  • reverse() ,数组反向排序

    const arr = [1, 2, 3, 4];
    arr.reverse(); // [4, 3, 2, 1]
    
  • sort() ,通过sort方法排序,默认是按照每项转换成字符串形式进行排序,不多说这个默认排序了,基本上不会用到。使用方式都是用sort接收一个比较函数,函数有两个参数,文字很苍白:

    const arr = [1, 9, 6, 15, 21, 0, 6];
    
    arr.sort((a, b) => {
      // 第一次进入函数的时候, a是9, b是1, 进入a > b条件,return 1的意思就是a到b的后面去 [1, 9]
      // 第二次进入函数, a是6, b是9, 进入a < b条件,return -1的意思是a到b的前面去[6, 9]
      // ...
      if (a < b) {
        return -1;
      }
      if (a > b) {
        return 1;
      }
      return 0;
    })
    
    // arr.sort((a, b) => a < b ? -1 : a > b ? 1 : 0); 简写
    
    console.log(arr); // [ 0, 1, 6, 6, 9, 15, 21 ]
    

4、操作方法

  • concat(...items) , 这个方法会重新生成一个数组,先生成数组副本,将参数依次添加到数末尾,返回新数组。如果参数是数组,会打平数组(只能打平一维数组)

    const arr = ['red'];
    colors.concat('green'); // ["red", "gree"]
    colors.concat('green', 'blue'); // ["red", "gree", "blue"]
    colors.concat(['green', 'pink']); // ["red", "green", "pink"]
    
  • slice(?start, ?end) ,用于截取数组,也是新生成数组,参数分别是开始的索引和结束索引,如果不用参数,会返回一个原数组的副本,但是这两个数组不是同一引用!

    const arr = [1, 2, 3, 4];
    arr.slice(); // [1, 2, 3, 4]
    arr.slice(2); // [3, 4]
    arr.slice(2, 3); // [3] 不包含end索引的值
    
  • splice(start, ?deleteCount, ...items) 会直接影响原数组

    • 删除,传入两个参数,开始的索引,结束索引,同样不会包含结束索引

      const arr = [1, 2, 3, 4];
      arr.splice(0, 1);  // [1] 返回删除项
      console.log(arr); // [2, 3, 4]
      arr.splice(0); // [2, 3, 4] 产出了2,3,4
      cosnole.log(arr); // []
      
    • 插入,传入三个参数,开始索引,0(要删除的元素个数),插入元素

      const arr = [2, 3, 4];
      arr.splice(0, 0, 0, 1); // [] 没有删除就返回空
      console.log(arr); // [0, 1, 2, 3, 4]
      arr.splice(0, 1, 9); // [0]
      console.log(arr); // [9, 1, 2, 3, 4]
      
    • 替换,在删除元素的同时可以在指定位置插入新元素,同样传三个参数,开始位置,要删除的个数,插入元素

      const arr = [1, 2, 6, 7, 8];
      arr.splice(2, 0, 3, 4, 5); // []
      console.log(arr); // [1, 2, 3, 4, 5, 6, 7, 8]
      

5、搜索和位置方法

ECMAScript提供两种搜索数组的方法:按照严格相等搜索和断言函数搜索。

严格相等

严格相等就是查找项与数组每一项都会进行全等(===)比较

  • indexOf(searchElement, ?fromIndex) ,可以传入一个搜索参数,或者两个在某个index找某项。找到返回index,找不到返回-1

    const arr = [1, 2, 3, 4, 5];
    console.log(arr.indexOf(1)); 		// 0
    console.log(arr.indexOf(1, 2)); // -1
    console.log(arr.indexOf(10)); 	// -1
    

    一个技巧性用法,~arr.indexOf(..)找到返回负数,找不到返回0。在if语句中经常使用。~(按位取反)以及二进制相关的说明搜索一下吧。

  • lastIndexOf(searchElement, ?fromIndex) ,使用方法与indexOf一样,区别是从数组右侧(最后一个)开始查找

  • Includes(searchElement, ?fromIndex) ,使用方法与上面一样,区别是返回布尔,表示是否至少找到一个与指定元素匹配的项。ps:这个方法是 ECMAScript 7 新增

断言函数

ECMAScript 也允许按照定义的断言函数搜索数组,每个索引都会调用这个函数。断言函数的返回 值决定了相应索引的元素是否被认为匹配。

断言函数接收 3 个参数:元素、索引和数组本身。其中元素是数组中当前搜索的元素,索引是当前 元素的索引,而数组就是正在搜索的数组。断言函数返回真值,表示是否匹配。

find()和 findIndex()方法使用了断言函数。这两个方法都从数组的最小索引开始。find()返回第一个匹配的元素,findIndex()返回第一个匹配元素的索引。这两个方法也都接收第二个可选的参数, 用于指定断言函数内部 this 的值。

const arr = [
    {
        name: 'carlos',
        age: 27
    },
    {
        name: 'xiaoming',
        name: 29
    }
];
arr.find((item, idx, array) => idx === 0); // {name: "carlos", age: 27}
arr.find((item, idx, array) => item.age < 30); // {name: "carlos", age: 27} 找到第一个就停止

6、迭代方法

ECMAScript定义了5个迭代方法,每个方法接收两个参数,函数和可选的绑定上下文的作用于对象。每个函数接收三个参数:数组元素,元素索引,数组本身。

  • every() ,对数组每一项都运行传入函数,如果每一项都返回true,则这个方法返回true

    const arr = [1, 2, 3, 4, 5];
    arr.every(item => item < 5); // false
    arr.every(item => item <= 5); // true
    
  • filter(),对数组每一项都传入函数,函数返回true的项会组成数组后返回。

    const arr = [
        {
            name: 'a',
            age: 10
        },
        {
            name: 'b',
            age: 18
        },
        {
            name: 'c',
            age: 22
        }
    ];
    const arrFilter = arr.filter(item => item.age > 10);
    console.log(arrFilter); // [ { name: 'b', age: 18 }, { name: 'c', age: 22 } ]
    
  • forEach(),对数组每一项都运行传入函数,没有返回值。(相当于for循环)

  • map(),对数组每一项运行传入函数,返回由每次函数调用的结果构成的数组。 (修改原数组)

    const arr = [
        {
            name: 'a',
            age: 10
        },
        {
            name: 'b',
            age: 18
        },
        {
            name: 'c',
            age: 22
        }
    ]
    arr.map(item => item.job = 'student'); // [ 'student', 'student', 'student' ]
    console.log(arr); //	[ { name: 'a', age: 10, job: 'student' },
                      //  { name: 'b', age: 18, job: 'student' },
                      //  { name: 'c', age: 22, job: 'student' } ]
    
  • some(),对数组的每一项都运行传入函数,如果有一项函数返回true则这个方法返回true

7、归并方法

ECMAScript 为数组提供了两个归并方法:reduce()和 reduceRight()。这两个方法都会迭代数 组的所有项,并在此基础上构建一个最终返回值。reduce()方法从数组第一项开始遍历到最后一项。 而 reduceRight()从最后一项开始遍历至第一项。

两个方法都接收两个参数,一个是每一项都运行的归并函数,一个是可选的以之为起点的初始值。函数可以接收4个参数:上一个归并值,当前项,当前项索引和数组本身。这个函数返回的任何值都会作为下一次调用同一个函数的第一个参数。如果没有给这两个方法传入可选第二个参数(作为归并起点值),则第一次迭代将从数组的第二项开始,因此传给归并函数的第一个参数是数组的第一项,第二个参数是数组的第二项。

  • reduce()

    const arr = [1 ,2, 3, 4, 5];
    let sum = arr.reduce((prev, cur, index, array) => prev + cur);
    // 第一次prev是1,cur是2
    // 第二次prev是第一次的prev + cur = 3,cur是3...
    console.log(sum); // 15
    
  • reduceRight()是反向进行归并

8、数组的其他方法

创建数组

除了new Array()和字面量方式,es6还新增了创建数组的静态方法:

from()用于将类数组转换为数组实例

of()用于将一组参数转为数组实例

迭代器方法

在 ES6 中,Array 的原型上暴露了 3 个用于检索数组内容的方法:keys()、values()和 entries()。keys()返回数组索引的迭代器,values()返回数组元素的迭代器,而 entries()返回 索引/值对的迭代器

复制和填充方法

ES6 新增了两个方法:批量复制方法 copyWithin(),以及填充数组方法 fill()。这两个方法的 函数签名类似,都需要指定既有数组实例上的一个范围,包含开始索引,不包含结束索引。使用这个方 法不会改变数组的大小。

转换方法

前面提到过,所有对象都有 toLocaleString()、toString()和 valueOf()方法。其中,valueOf() 返回的还是数组本身。而 toString()返回由数组中每个值的等效字符串拼接而成的一个逗号分隔的 字符串。也就是说,对数组的每个值都会调用其 toString()方法,以得到最终的字符串。join方法可以按照番薯分割生成字符串。