Skip to main content

JS 数组的总结

· 7 min read
Zeffon Wu

写一篇关于 js 数组相关操作的总结,方便后续查阅。

数组是一种类列表对象,它的原型中提供了遍历和修改元素的相关操作。JavaScript 数组的长度和元素类型都是非固定的。因为数组的长度可随时改变,并且其数据在内存中也可以不连续,所以 JavaScript 数组不一定是密集型的,这取决于它的使用方式。更多可以在MDN上查阅。

参考自各位大佬:

  1. JS 中循环遍历数组方式总结
  2. JavaScript 高性能数组去重

数组的基本操作

  1. 创建数组

    const fruits = ["Apple", "Banana"];
    console.log(fruits.length); // 2
  2. 新增元素

    push 新增元素到数组的末尾

    const fruits = ["Apple", "Banana"];
    fruits.push("Orange");
    console.log(fruits); // ['Apple', 'Banana', 'Orange']

    unshift 新增元素到数组的头部

    const fruits = ["Apple", "Banana"];
    fruits.unshift("Mango");
    console.log(fruits); // ['Mango', 'Apple', 'Banana']
  3. 查询元素

    通过索引访问数组元素

    const fruits = ["Apple", "Banana"];
    let apple = fruits[0];
    console.log(apple); // Apple

    找出某个元素在数组中的索引

    const fruits = ["Apple", "Banana"];
    fruits.push("Mango"); // ['Apple', 'Banana', 'Mango']["Apple", "Banana", "Mango"]
    let pos = fruits.indexOf("Banana");
    console.log(pos); // 1
  4. 修改元素

    const fruits = ["Apple", "Banana", "Mango"];
    fruits[0] = "Orange";
    console.log(fruits); // ['Orange', 'Banana', 'Mango']
  5. 删除元素

    pop 删除数组末尾的元素

    const fruits = ["Apple", "Banana", "Mango"];
    fruits.pop();
    console.log(fruits); // ['Apple', 'Banana']

    shift 删除数组头部元素

    const fruits = ["Apple", "Banana", "Mango"];
    fruits.shift();
    console.log(fruits); // ['Banana', 'Mango']

数组遍历

js 数组的索引是从 0 开始的,第一个元素的索引为 0,最后一个元素的索引等于该数组的 长度 length 减 1。如果指定的索引是一个无效值,js 数组并不会报错,而是会返回 undefined

for 循环

  • 它用途广泛,但是当我们要遍历数组时也很麻烦。

  • 如果我们不想从第一个数组元素开始循环时它仍然很有用,用其他的循环机制很难做到这一点。

    const array = [0, 1, 2, 3, 4, 5, 6];
    for (let i = 0; i < array.length; i++) {
    console.log(i);
    }

for-in 循环

对象也可以用此进行遍历 key

for-in 访问继承属性的实际用途是:遍历对象的所有可枚举属性。

for-in 不是循环遍历数组的好方法:

  • 它访问的是属性键,而不是值。

  • 作为属性键,数组元素的索引是字符串,而不是数字。

  • 它访问的是所有可枚举的属性键(自己的和继承的),而不仅仅是 Array 元素的那些。

    const array = [0, 1, 2, 3, 4, 5, 6];
    for (const key in array) {
    console.log(key);
    }

forEach 循环

缺点:

  • 不能在它的循环体中使用 await。

  • 不能提前退出 forEach() 循环。而在 for 循环中可以使用 break。

    const array = [0, 1, 2, 3, 4, 5, 6];
    array.forEach((item, index) => {
    console.log(item, index);
    });

for-of 循环

for-of 在循环遍历数组时非常有效:

  • 用来遍历数组元素。

  • 可以使用 await

  • 甚至可以将 break 和 continue 用于外部作用域。

    const array = [0, 1, 2, 3, 4, 5, 6];
    for (const item of array) {
    console.log(item);
    }

数组去重

数组去重一般都是两个数组之间进行比较去重的。

双重 for 循环

将两个数组合为一个数组,然后双重 for 循环,在外层遍历所有元素,内层进行检查元素是否重复。 这种双重循环判断的去重的效率是极差的

function distinct(arr1, arr2) {
let arr = arr1.concat(arr2);
const len = arr.length;
for (let i = 0; i < len; i++) {
for (let j = i + 1; j < len; j++) {
if (arr[i] == arr[j]) {
arr.splice(j, 1);
len--;
j--;
}
}
}
return arr;
}

Array.filter + indexOf

将两个数组拼接为一个数组,然后使用 ES6 中的 Array.filter() 遍历数组,并结合 indexOf 来排除重复项

function distinct(arr1, arr2) {
let arr = arr1.concat(arr2);
return arr.filter((item, index) => {
return arr.indexOf(item) === index;
});
}

for...of + includes()

function distinct(arr1, arr2) {
let arr = arr1.concat(arr2);
let result = [];
for (let i of arr) {
!result.includes(i) && result.push(i);
}
return result;
}

Array.sort()

合并后数组进行排序,再比较相邻元素去重,效率会比前面三个高。

function distinct(arr1, arr2) {
let arr = arr1.concat(arr2);
arr = arr.sort();
const len = arr.length;
let result = [arr[0]];
for (let i = 1; i < len; i++) {
arr[i] !== arr[i - 1] && result.push(arr[i]);
}
return result;
}

new Set()

使用 ES6 新增的 new Set() 方法来判断去重。这种方式比较推荐。

function distinct(arr1, arr2) {
return Array.from(new Set([...arr1, ...arr2]));
}

for...of + Object

首先创建一个空对象,然后用 for 循环遍历。利用对象的属性不会重复这一特性,校验数组元素是否重复。 这种效率是最高的。

function distinct(arr1, arr2) {
let arr = arr1.concat(arr2);
let arr = a.concat(b);
let result = [];
let obj = {};
for (let i of arr) {
if (!obj[i]) {
result.push(i);
obj[i] = 1;
}
}
return result;
}