Appearance
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