Skip to content
On this page

JavaScript 数组操作

数组是JavaScript中最重要的数据结构之一,用于存储有序的数据集合。掌握数组的各种操作方法对于高效编程至关重要。

数组创建

JavaScript提供了多种创建数组的方式:

数组字面量语法

最常用和推荐的创建方式:

javascript
const arr1 = [1, 2, 3, 4, 5];
const arr2 = ['apple', 'banana', 'orange'];
const arr3 = [1, 'hello', true, { name: 'John' }, [1, 2, 3]];
const emptyArray = []; // 空数组

Array构造函数

javascript
// 创建指定长度的数组
const arr1 = new Array(5); // [empty × 5],长度为5的空数组
const arr2 = new Array(1, 2, 3, 4, 5); // [1, 2, 3, 4, 5]

// Array.of() - 创建包含指定元素的数组
const arr3 = Array.of(5); // [5],而不是长度为5的数组
const arr4 = Array.of(1, 2, 3); // [1, 2, 3]

Array.from()

从类数组对象或可迭代对象创建数组:

javascript
// 从类数组对象创建
const arr1 = Array.from('hello'); // ['h', 'e', 'l', 'l', 'o']
const arr2 = Array.from({ length: 5 }, (_, index) => index); // [0, 1, 2, 3, 4]

// 从Set创建
const set = new Set([1, 2, 3]);
const arr3 = Array.from(set); // [1, 2, 3]

fill() 方法

填充数组:

javascript
const arr = new Array(5).fill(0); // [0, 0, 0, 0, 0]
const arr2 = new Array(3).fill('empty'); // ['empty', 'empty', 'empty']

// 部分填充
const arr3 = [1, 2, 3, 4, 5];
arr3.fill(0, 2, 4); // [1, 2, 0, 0, 5],从索引2到4填充0

数组检查

判断是否为数组:

javascript
// Array.isArray() - 推荐方法
Array.isArray([1, 2, 3]); // true
Array.isArray('not array'); // false

// instanceof - 可能不适用于跨框架情况
[1, 2, 3] instanceof Array; // true

// Object.prototype.toString - 最可靠方法
Object.prototype.toString.call([1, 2, 3]); // '[object Array]'

数组遍历方法

forEach - 基本遍历

javascript
const numbers = [1, 2, 3, 4, 5];
numbers.forEach((num, index, array) => {
  console.log(`Index ${index}: ${num}`);
  // 注意:forEach不能使用break或return来中断循环
});

map - 转换数组

创建新数组,每个元素是原数组元素经过函数处理后的结果:

javascript
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(num => num * 2); // [2, 4, 6, 8, 10]

// 复杂转换示例
const users = [
  { name: 'John', age: 30 },
  { name: 'Jane', age: 25 }
];
const userDescriptions = users.map(user => `${user.name} is ${user.age} years old`);
// ['John is 30 years old', 'Jane is 25 years old']

filter - 过滤元素

创建新数组,包含所有满足条件的元素:

javascript
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const evens = numbers.filter(num => num % 2 === 0); // [2, 4, 6, 8, 10]

// 复杂过滤示例
const products = [
  { name: 'Laptop', price: 1000, category: 'Electronics' },
  { name: 'Book', price: 20, category: 'Education' },
  { name: 'Phone', price: 800, category: 'Electronics' }
];
const expensiveProducts = products.filter(product => product.price > 500);

find 和 findIndex - 查找元素

javascript
const users = [
  { id: 1, name: 'John' },
  { id: 2, name: 'Jane' },
  { id: 3, name: 'Bob' }
];

// find - 返回第一个满足条件的元素
const user = users.find(u => u.id === 2); // { id: 2, name: 'Jane' }

// findIndex - 返回第一个满足条件的元素的索引
const index = users.findIndex(u => u.name === 'Bob'); // 2

some 和 every - 条件检查

javascript
const numbers = [1, 2, 3, 4, 5];

// some - 检查是否有至少一个元素满足条件
const hasEven = numbers.some(num => num % 2 === 0); // true

// every - 检查是否所有元素都满足条件
const allPositive = numbers.every(num => num > 0); // true

归约方法

reduce - 归约操作

将数组元素归约为单个值:

javascript
const numbers = [1, 2, 3, 4, 5];

// 求和
const sum = numbers.reduce((accumulator, currentValue) => accumulator + currentValue, 0); // 15

// 求积
const product = numbers.reduce((acc, curr) => acc * curr, 1); // 120

// 统计字符出现次数
const str = 'hello world';
const charCount = [...str].reduce((acc, char) => {
  acc[char] = (acc[char] || 0) + 1;
  return acc;
}, {}); // { h: 1, e: 1, l: 3, o: 2, ' ': 1, w: 1, r: 1, d: 1 }

// 数组扁平化
const nested = [[1, 2], [3, 4], [5, 6]];
const flat = nested.reduce((acc, arr) => acc.concat(arr), []); // [1, 2, 3, 4, 5, 6]

reduceRight - 从右到左归约

javascript
const arr = ['a', 'b', 'c'];
const result = arr.reduceRight((acc, curr) => acc + curr, ''); // 'cba'

数组搜索方法

includes - 检查元素是否存在

javascript
const arr = [1, 2, 3, 4, 5];
arr.includes(3); // true
arr.includes(6); // false
arr.includes(3, 3); // false,从索引3开始搜索

indexOf 和 lastIndexOf

javascript
const arr = [1, 2, 3, 2, 4, 2, 5];

// indexOf - 从前往后查找
arr.indexOf(2); // 1
arr.indexOf(2, 2); // 3,从索引2开始查找

// lastIndexOf - 从后往前查找
arr.lastIndexOf(2); // 5

数组变异方法

这些方法会直接修改原数组:

添加/删除元素

javascript
const arr = [1, 2, 3];

// push - 末尾添加元素
arr.push(4); // [1, 2, 3, 4],返回新长度

// pop - 移除末尾元素
const last = arr.pop(); // 4,arr变为[1, 2, 3]

// unshift - 开头添加元素
arr.unshift(0); // [0, 1, 2, 3],返回新长度

// shift - 移除开头元素
const first = arr.shift(); // 0,arr变为[1, 2, 3]

splice - 万能数组操作方法

javascript
const arr = [1, 2, 3, 4, 5];

// 删除元素:splice(start, deleteCount)
const deleted = arr.splice(2, 2); // [3, 4],arr变为[1, 2, 5]

// 插入元素:splice(start, 0, items)
arr.splice(2, 0, 'a', 'b'); // arr变为[1, 2, 'a', 'b', 5]

// 替换元素:splice(start, deleteCount, items)
arr.splice(1, 2, 'x', 'y'); // 从索引1开始删除2个元素,插入'x'和'y'

reverse - 反转数组

javascript
const arr = [1, 2, 3, 4, 5];
arr.reverse(); // [5, 4, 3, 2, 1],修改原数组

sort - 排序

javascript
// 默认按字符串排序
const arr1 = [10, 2, 1, 20];
arr1.sort(); // [1, 10, 2, 20],按字符串排序

// 数字排序
const arr2 = [10, 2, 1, 20];
arr2.sort((a, b) => a - b); // [1, 2, 10, 20],升序
arr2.sort((a, b) => b - a); // [20, 10, 2, 1],降序

// 字符串排序
const fruits = ['banana', 'apple', 'cherry'];
fruits.sort(); // ['apple', 'banana', 'cherry']

// 对象排序
const users = [
  { name: 'John', age: 30 },
  { name: 'Jane', age: 25 },
  { name: 'Bob', age: 35 }
];
users.sort((a, b) => a.age - b.age); // 按年龄升序排列

非变异方法

这些方法返回新数组,不修改原数组:

slice - 提取子数组

javascript
const arr = [1, 2, 3, 4, 5];
const sub1 = arr.slice(1, 4); // [2, 3, 4],从索引1到4(不包括4)
const sub2 = arr.slice(2); // [3, 4, 5],从索引2到末尾
const sub3 = arr.slice(); // [1, 2, 3, 4, 5],完整复制数组

concat - 合并数组

javascript
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combined = arr1.concat(arr2); // [1, 2, 3, 4, 5, 6]
const arr3 = [7, 8];
const combined2 = arr1.concat(arr2, arr3); // [1, 2, 3, 4, 5, 6, 7, 8]

join - 数组转字符串

javascript
const arr = ['apple', 'banana', 'orange'];
arr.join(', '); // 'apple, banana, orange'
arr.join(' - '); // 'apple - banana - orange'
arr.join(''); // 'applebananaorange'

扁平化方法(ES2019)

flat - 数组扁平化

javascript
const nested = [1, [2, 3], [4, [5, 6]]];
nested.flat(); // [1, 2, 3, 4, [5, 6]],默认扁平化一层
nested.flat(2); // [1, 2, 3, 4, 5, 6],扁平化两层
nested.flat(Infinity); // [1, 2, 3, 4, 5, 6],完全扁平化

flatMap - map + flat

javascript
const arr = [1, 2, 3];
const doubledAndFlat = arr.flatMap(num => [num, num * 2]); 
// [1, 2, 2, 4, 3, 6],等价于 arr.map(x => [x, x*2]).flat()

数组解构

ES6解构语法在数组中的应用:

javascript
const numbers = [1, 2, 3, 4, 5];

// 基本解构
const [first, second, third] = numbers;
console.log(first, second, third); // 1, 2, 3

// 跳过元素
const [a, , c] = numbers; // 跳过第二个元素
console.log(a, c); // 1, 3

// 剩余元素
const [x, y, ...rest] = numbers;
console.log(x, y, rest); // 1, 2, [3, 4, 5]

// 默认值
const [p, q, r = 10] = [1, 2];
console.log(r); // 10

// 交换变量
let a = 1, b = 2;
[a, b] = [b, a]; // a=2, b=1

实用技巧和模式

数组去重

javascript
// 使用Set
const arr = [1, 2, 2, 3, 3, 4];
const unique = [...new Set(arr)]; // [1, 2, 3, 4]

// 使用filter
const unique2 = arr.filter((item, index) => arr.indexOf(item) === index);

// 对象数组去重
const users = [
  { id: 1, name: 'John' },
  { id: 2, name: 'Jane' },
  { id: 1, name: 'John' } // 重复
];
const uniqueUsers = users.filter((user, index, self) => 
  index === self.findIndex(u => u.id === user.id)
);

数组分组

javascript
const products = [
  { category: 'Electronics', name: 'Laptop' },
  { category: 'Books', name: 'JavaScript Guide' },
  { category: 'Electronics', name: 'Phone' },
  { category: 'Books', name: 'Python Book' }
];

const grouped = products.reduce((acc, product) => {
  const category = product.category;
  acc[category] = acc[category] || [];
  acc[category].push(product);
  return acc;
}, {});
// {
//   Electronics: [{ category: 'Electronics', name: 'Laptop' }, ...],
//   Books: [{ category: 'Books', name: 'JavaScript Guide' }, ...]
// }

数组分块

javascript
function chunkArray(arr, chunkSize) {
  const chunks = [];
  for (let i = 0; i < arr.length; i += chunkSize) {
    chunks.push(arr.slice(i, i + chunkSize));
  }
  return chunks;
}

const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
const chunks = chunkArray(numbers, 3); // [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

数组乱序(洗牌算法)

javascript
function shuffleArray(arr) {
  const shuffled = [...arr]; // 创建副本
  for (let i = shuffled.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]; // 交换
  }
  return shuffled;
}

const numbers = [1, 2, 3, 4, 5];
const shuffled = shuffleArray(numbers);

性能考虑

避免在循环中使用数组方法

javascript
// 不推荐:在循环中使用map/filter等
for (let i = 0; i < largeArray.length; i++) {
  const processed = largeArray[i].map(item => item * 2); // 每次都创建新数组
}

// 推荐:先处理再循环
const processed = largeArray.map(item => item * 2);
for (const item of processed) {
  // 处理逻辑
}

选择合适的迭代方法

  • 简单遍历:使用for或for...of
  • 需要索引:使用forEach或传统for循环
  • 需要转换:使用map
  • 需要过滤:使用filter
  • 需要聚合:使用reduce