在 JavaScript 中,数组操作是日常开发中必不可少的一环。本文详细介绍几种常用的数组添加、移除、合并、过滤等操作方法,帮助你高效管理数据。无论是向数组添加元素、删除元素、还是查找和排序,本篇内容都涵盖了常用的数组处理技巧,便于用户在不同场景中灵活应用这些技巧。

JS 添加/移除数组元素

在 JavaScript 中,数组提供了多种方法来添加或移除元素。这些方法包括 pushpopshiftunshift,它们可以用来操作数组的尾端和首端的元素。

添加元素

  • arr.push(...items): 在数组的尾端添加一个或多个元素。
  • arr.unshift(...items): 在数组的首端添加一个或多个元素。

移除元素

  • arr.pop(): 移除数组尾端的最后一个元素并返回它。
  • arr.shift(): 移除数组首端的第一个元素并返回它。

使用展开运算符

展开运算符 ... 可以用来将一个数组的所有元素添加到另一个数组中。

示例代码

// 初始化数组
let arr = ["Apple", "Banana"];

// 使用 push() 添加元素到数组尾端
arr.push("Orange", "Peach");
console.log(arr); // ["Apple", "Banana", "Orange", "Peach"]

// 使用 pop() 从数组尾端移除元素
let last = arr.pop();
console.log(last); // "Peach"
console.log(arr); // ["Apple", "Banana", "Orange"]

// 使用 shift() 从数组首端移除元素
let first = arr.shift();
console.log(first); // "Apple"
console.log(arr); // ["Banana", "Orange"]

// 使用 unshift() 添加元素到数组首端
arr.unshift("Strawberry", "Lemon");
console.log(arr); // ["Strawberry", "Lemon", "Banana", "Orange"]

// 使用展开运算符合并数组
let fruits = ["Apple", "Banana"];
let moreFruits = ["Orange", "Peach"];
fruits.push(...moreFruits);
console.log(fruits); // ["Apple", "Banana", "Orange", "Peach"]

let berries = ["Strawberry", "Blueberry"];
fruits.unshift(...berries);
console.log(fruits); // ["Strawberry", "Blueberry", "Apple", "Banana", "Orange", "Peach"]

JS 中使用splice 修改数组

JavaScript 数组的splice 方法可以用来添加、删除或替换数组中的元素,使用方式非常灵活。

删除数组元素

使用 splice(start, deleteCount) 可以从索引 start 删除 deleteCount 个元素。

let arr = ["I", "study", "JavaScript"];
arr.splice(1, 1); // 从索引 1 删除 1 个元素
console.log(arr); // 输出: ["I", "JavaScript"]

替换数组元素

splice(start, deleteCount, ...items) 从索引 start 删除 deleteCount 个元素,并插入 ...items

let arr = ["I", "study", "JavaScript", "right", "now"];
arr.splice(0, 3, "Let's", "dance"); // 删除前三个元素,添加两个新元素
console.log(arr); // 输出: ["Let's", "dance", "right", "now"]

插入元素

deleteCount 设置为 0splice() 可以在不删除任何元素的情况下插入新元素。

let arr = ["I", "study", "JavaScript"];
arr.splice(2, 0, "complex", "language"); // 从索引 2 开始插入元素
console.log(arr); // 输出: ["I", "study", "complex", "language", "JavaScript"]

使用负索引

splice() 允许使用负索引,从数组末尾开始计算位置。

let arr = [1, 2, 5];
arr.splice(-1, 0, 3, 4); // 从数组末尾前一位开始插入元素
console.log(arr); // 输出: [1, 2, 3, 4, 5]

JS 中使用slice提取数组的子集或者创建数组的副本

使用数组的 slice() 方法可以方便地在不修改原数组的情况下,提取数组的子集或者创建数组的副本。这在编程中非常有用,特别是当你需要保留原数组不变,同时又需要操作数组的一部分时。

基本用法

arr.slice([start], [end]) 从索引 startend(不包括 end)复制元素到一个新数组。

startend 参数都可以是负数,表示从数组末尾开始计算。

创建数组副本

调用 arr.slice() 不带任何参数将创建原数组的一个浅副本。

示例代码

let arr = ["t", "e", "s", "t"];

// 复制从位置 1 到位置 3 的元素
console.log(arr.slice(1, 3)); // 输出: ["e", "s"]

// 复制从位置 -2 到尾端的元素
console.log(arr.slice(-2)); // 输出: ["s", "t"]

// 创建数组的副本
let arrCopy = arr.slice();
console.log(arrCopy); // 输出: ["t", "e", "s", "t"]

JS 中使用 concat 方法合并数组

arr.concat() 是 JavaScript 中用于合并数组的方法,它创建一个新数组,包含原数组 arr 和作为参数传递的数组或值。

arr.concat(arg1, arg2, ...) 可以接受任意数量的参数,无论是数组还是单独的值。 如果参数是数组,它会将数组中的元素复制到新数组中。 如果参数不是数组,它会直接将参数复制到新数组中。

concat() 不会改变现有的数组,而是返回一个新数组。

// 初始化数组
let arr = [1, 2];

// 使用 concat() 合并数组
console.log(arr.concat([3, 4])); // 输出: [1, 2, 3, 4]
console.log(arr.concat([3, 4], [5, 6])); // 输出: [1, 2, 3, 4, 5, 6]
console.log(arr.concat([3, 4], 5, 6)); // 输出: [1, 2, 3, 4, 5, 6]

concat 类数组对象(具有索引和 length 属性的对象)时,通常是将其作为单个元素被添加。如果类数组对象有 Symbol.isConcatSpreadable 属性,并且其值为 true,则其元素会被 concat() 当作数组处理并被添加到新数组中。

// 初始化数组
let arr = [1, 2];

let arrayLike = { 0: "something", length: 1 };
console.log(arr.concat(arrayLike)); // 输出: [1, 2, arrayLike]

// 类数组对象具有 Symbol.isConcatSpreadable 属性
let arrayLikeWithSpreadable = {
  0: "something",
  1: "else",
  [Symbol.isConcatSpreadable]: true,
  length: 2,
};
console.log(arr.concat(arrayLikeWithSpreadable)); // 输出: [1, 2, "something", "else"]

JS 中使用 arr.forEach 遍历数组

当我们需要遍历一个数组时 —— 我们可以使用 forEachforfor..of

数组方法 forEach 遍历数组

arr.forEach(function(item, index, array) {...}) 允许你为数组 arr 中的每个元素 item 执行一个函数。

函数可以接受三个参数:当前元素 item,当前元素的索引 index,以及被遍历的数组 array

// 定义一个数组
let characters = ["Bilbo", "Gandalf", "Nazgul"];

// 使用 forEach() 显示数组的每个元素
characters.forEach(alert);

// 使用 forEach() 更详细地显示每个元素及其索引
characters.forEach((item, index, array) => {
  console.log(`${item} is at index ${index} in ${array}`);
});

for 循环遍历数组

for 循环:

let arr = ["Apple", "Orange", "Pear"];
for (let i = 0; i < arr.length; i++) {
  alert(arr[i]);
}

for..of 循环:

let fruits = ["Apple", "Orange", "Plum"];
for (let fruit of fruits) {
  alert(fruit);
}

JS 数组中搜索特定的元素或对象

indexOflastIndexOf

arr.indexOf(item, from) 用于查找 item 从索引 from 开始的第一个出现的位置。如果找不到,返回 -1

arr.lastIndexOf(item, from) 类似于 indexOf,但它从数组的末尾开始向前搜索。

// 初始化数组
let fruits = ["Apple", "Orange", "Apple"];

// 使用 indexOf 和 lastIndexOf
console.log(fruits.indexOf("Apple")); // 0
console.log(fruits.lastIndexOf("Apple")); // 2

includes

arr.includes(item, from) 用于检查数组中是否包含 item,从索引 from 开始搜索。如果找到,返回 true;否则,返回 false

includes 方法可以正确处理 NaN 值,这是 indexOf 无法做到的。

// 初始化数组
let arr = [1, 0, false];
console.log(arr.includes(1)); // true

const arr = [NaN];
alert(arr.indexOf(NaN)); // -1(错,应该为 0)
alert(arr.includes(NaN)); // true(正确)

findfindIndex/findLastIndex

arr.find(callback) 用于找到第一个满足 callback 函数条件的元素。如果没有找到符合条件的元素,返回 undefined

arr.findIndex(callback) 类似于 find,但返回满足条件的元素的索引,如果没有找到,则返回 -1

arr.findLastIndex(callback) 类似于 findIndex,但它从数组的末尾开始向前搜索。

// 使用 find 和 findIndex
let users = [
  { id: 1, name: "John" },
  { id: 2, name: "Pete" },
  { id: 3, name: "Mary" },
];

let user = users.find((item) => item.id == 1);
console.log(user.name); // John

console.log(users.findIndex((user) => user.name == "John")); // 0

// 使用 findLastIndex
let usersWithDuplicate = [
  { id: 1, name: "John" },
  { id: 2, name: "Pete" },
  { id: 3, name: "Mary" },
  { id: 4, name: "John" },
];

console.log(usersWithDuplicate.findLastIndex((user) => user.name == "John")); // 3

filter

arr.filter(callback) 方法创建一个新数组,其中包含所有通过由 callback 函数实现的测试的元素。

callback 函数接受三个参数:当前元素 item,当前元素的索引 index,以及数组本身 array

如果 callback 函数返回 true,当前元素 item 会被添加到新数组中。如果没有元素通过测试(即 callback 函数总是返回 false),则返回一个空数组。

// 初始化用户数组
let users = [
  { id: 1, name: "John" },
  { id: 2, name: "Pete" },
  { id: 3, name: "Mary" },
];

// 使用 filter() 方法找到 id 小于 3 的用户
let someUsers = users.filter((item) => item.id < 3);

console.log(someUsers.length); // 输出: 2
console.log(someUsers); // 输出: [{id: 1, name: "John"}, {id: 2, name: "Pete"}]

JS 数组转换

map

当我们需要遍历数组并返回每个元素的数据时 —— 我们可以使用 map。

arr.map(callback) 创建一个新数组,其中包含对原数组中每个元素调用 callback 函数的结果。

callback 函数接受三个参数:当前元素 item,当前元素的索引 index,以及数组本身 array

// 使用 map 方法
let lengths = ["Bilbo", "Gandalf", "Nazgul"].map((item) => item.length);
console.log(lengths); // [5, 7, 6]

sort(fn)

arr.sort(compareFunction) 对数组进行原位排序,改变原数组的元素顺序。

如果没有提供 compareFunction,元素默认按字符串 Unicode 码点进行排序。使用 localeCompare 可以根据本地语言环境的特定顺序来排序字符串。

// 使用 sort 方法排序字符串
let countries = ["Österreich", "Andorra", "Vietnam"];

countries.sort((a, b) => (a > b ? 1 : -1));
console.log(countries); //  ['Andorra', 'Vietnam', 'Österreich'](错的)

countries.sort((a, b) => a.localeCompare(b));
console.log(countries); // ['Andorra', 'Österreich', 'Vietnam'](对的!)

为了按数字大小排序,需要提供一个 compareFunction,比较函数只需要返回一个正数表示“大于”,一个负数表示“小于”。

// 使用 sort 方法排序数字
let numbers = [1, 2, 15];

numbers.sort();
console.log(numbers); // [1, 15, 2]

numbers.sort((a, b) => a - b);
console.log(numbers); // [1, 2, 15]

reverse

数组倒序:

let arr = [1, 2, 3, 4, 5];
arr.reverse();

alert(arr); // 5,4,3,2,1

split/join

在 JavaScript 中,splitjoin 方法是处理字符串和数组的有用工具。split 方法可以将一个字符串分割成数组,而 join 方法则可以将数组元素合并成一个字符串。

split 方法

let names = "John, Pete, Mary";
let nameArray = names.split(", ");
// nameArray 现在是 ['John', 'Pete', 'Mary']

还可以限制结果数组的长度,通过提供一个可选的第二个参数给 split 方法。

let names = "Bilbo, Gandalf, Nazgul, Saruman";
let limitedArray = names.split(", ", 2);
// limitedArray 现在是 ['Bilbo', 'Gandalf']

调用带有空参数的 split,会将字符串拆分为字母数组:

let str = "test";

alert(str.split("")); // t,e,s,t

join 方法

split 相反,join 方法会取一个数组并将其元素连接成一个字符串。元素之间的连接符由 join 方法的参数指定。

let nameArray = ["Bilbo", "Gandalf", "Nazgul"];
let names = nameArray.join("; ");
// names 现在是 'Bilbo; Gandalf; Nazgul'

reduce/reduceRight

在 JavaScript 中,reducereduceRight 是数组方法,用于将数组中的所有元素归纳为单个值。这些方法通常用于累加数值或结合数组中的元素。

reduce 方法接受一个回调函数和一个可选的初始值作为参数。

let value = arr.reduce(
  function (accumulator, item, index, array) {
    // ...
  },
  [initial]
);

回调函数被执行时,它会接收四个参数:累加器(accumulator)、当前元素(item)、当前索引(index)和数组本身(array)。传递给 reduce 的函数仅使用了 2 个参数,通常这就足够了。

accumulator 是上一次回调返回的值,对于第一次调用,它是初始值(如果提供了的话)。

let arr = [1, 2, 3, 4, 5];

// 使用 reduce 来计算数组的总和
let sum = arr.reduce((accumulator, current) => accumulator + current, 0);
alert(sum); // 输出 15

如果没有提供初始值,reduce 会使用数组的第一个元素作为初始值,并从第二个元素开始处理。

reduceRight 方法的工作原理与 reduce 相同,但它从数组的末尾开始向前工作,而不是从头开始。

Array.isArray 检测一个值是否为数组

在 JavaScript 中,由于数组是特殊类型的对象,我们不能仅仅通过 typeof 操作符来区分数组和普通对象。

alert(typeof {}); // object
alert(typeof []); // object(相同)

为了解决这个问题,JavaScript 提供了 Array.isArray() 方法,它可以准确地检测一个值是否为数组。

// 检测普通对象
console.log(Array.isArray({})); // 输出 false

// 检测数组
console.log(Array.isArray([])); // 输出 true

结语

通过本文的细致讲解,你可以轻松掌握 JavaScript 数组操作的常用方法。希望以上示例代码与方法说明能帮助你在日常开发中处理数组更加得心应手。


也可以看看