← JavaScript对象 没有下一篇了 →

JavaScript数组

原创 2026-03-13 JavaScript 已有人查阅

JavaScript数组指南:从基础操作到高阶方法

什么是数组?

数组是JavaScript中最基础也最常用的数据结构之一。数组就是一个可以存储多个值的变量,这些值在内存中拥有各自的存储位置,但共享同一个数组名称。

可以把数组想象成一个有序的容器,容器中的每个位置都有一个编号(索引),通过这个编号我们可以快速找到对应位置的值。

// 一个简单的数组示例
let fruits = ['苹果', '香蕉', '橙子', '葡萄'];
console.log(fruits);  // ['苹果', '香蕉', '橙子', '葡萄']

数组的核心特性

  • 索引从0开始:第一个元素的索引是0,第二个是1,依次类推

  • 动态长度:数组大小可以动态变化,不需要预先指定

  • 混合类型:一个数组可以包含不同类型的数据

  • 引用类型:数组是对象,赋值和传递时按引用操作

创建数组的三种方式

1. 数组字面量(推荐)

这是最简单、最直观的创建方式,使用方括号 [] 包裹元素:

// 空数组
let emptyArray = [];

// 包含数字的数组
let numbers = [10, 20, 30, 40, 50];

// 包含字符串的数组
let students = ['张三', '李四', '王五', '赵六'];

// 混合类型数组
let mixed = ['张三', 25, true, { city: '北京' }, [1, 2, 3]];

console.log(numbers[0]);  // 10
console.log(students[1]);  // 李四

个人经验:日常开发中,我几乎都用数组字面量创建数组,代码简洁明了,性能也很好。

2. 使用new关键字

// 创建空数组
let fruits = new Array();

// 创建指定长度的数组
let fixedLength = new Array(5);  // 创建一个长度为5的空数组
console.log(fixedLength);  // [empty × 5]

// 创建包含元素的数组
let colors = new Array('红色', '蓝色', '绿色', '黄颜色');
console.log(colors);  // ['红色', '蓝色', '绿色', '黄颜色']

// 遍历数组
for (let i = 0; i < colors.length; i++) {
    console.log(colors[i]);
}

3. 使用Array构造函数

// 直接传入元素
let languages = new Array('JavaScript', 'Python', 'Java', 'C++');
console.log(languages);  // ['JavaScript', 'Python', 'Java', 'C++']

// 使用of方法(ES6)
let digits = Array.of(1, 2, 3, 4, 5);
console.log(digits);  // [1, 2, 3, 4, 5]

// 从类数组对象创建
let str = 'Hello';
let charArray = Array.from(str);
console.log(charArray);  // ['H', 'e', 'l', 'l', 'o']

数组的基本操作

访问数组元素

let books = ['JavaScript高级程序设计', '你不知道的JS', 'ES6入门指南', '算法图解'];

// 通过索引访问
console.log(books[0]);  // JavaScript高级程序设计
console.log(books[2]);  // ES6入门指南

// 访问第一个元素
console.log(books[0]);  // JavaScript高级程序设计

// 访问之后一个元素
console.log(books[books.length - 1]);  // 算法图解

// 使用at方法(ES2022)
console.log(books.at(-1));  // 算法图解(更优雅的写法)

修改数组元素

let scores = [85, 92, 78, 90, 88];
console.log('原始数组:', scores);

// 修改指定索引的值
scores[2] = 95;
console.log('修改后:', scores);  // [85, 92, 95, 90, 88]

// 批量修改
for (let i = 0; i < scores.length; i++) {
    if (scores[i] < 90) {
        scores[i] += 5;  // 给低于90分的加5分
    }
}
console.log('加分后:', scores);

添加元素

let fruits = ['苹果', '香蕉'];
console.log('初始数组:', fruits);

// push() - 在末尾添加一个或多个元素
fruits.push('橙子');
console.log('push后:', fruits);  // ['苹果', '香蕉', '橙子']

fruits.push('葡萄', '西瓜');
console.log('push多个:', fruits);  // ['苹果', '香蕉', '橙子', '葡萄', '西瓜']

// unshift() - 在开头添加一个或多个元素
fruits.unshift('草莓');
console.log('unshift后:', fruits);  // ['草莓', '苹果', '香蕉', '橙子', '葡萄', '西瓜']

// 通过索引添加(如果索引大于当前长度)
fruits[10] = '芒果';
console.log('通过索引添加:', fruits);  // 中间会有空位

删除元素

let fruits = ['苹果', '香蕉', '橙子', '葡萄', '西瓜'];
console.log('初始数组:', fruits);

// pop() - 删除之后一个元素
let lastFruit = fruits.pop();
console.log('删除的元素:', lastFruit);  // 西瓜
console.log('pop后:', fruits);  // ['苹果', '香蕉', '橙子', '葡萄']

// shift() - 删除第一个元素
let firstFruit = fruits.shift();
console.log('删除的元素:', firstFruit);  // 苹果
console.log('shift后:', fruits);  // ['香蕉', '橙子', '葡萄']

// splice() - 删除指定位置的元素
let removed = fruits.splice(1, 1);  // 从索引1开始删除1个元素
console.log('删除的元素:', removed);  // ['橙子']
console.log('splice后:', fruits);  // ['香蕉', '葡萄']

常用数组方法详解

1. concat() - 合并数组

const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const arr3 = [7, 8, 9];

// 合并两个数组
const combined = arr1.concat(arr2);
console.log(combined);  // [1, 2, 3, 4, 5, 6]

// 合并多个数组
const all = arr1.concat(arr2, arr3);
console.log(all);  // [1, 2, 3, 4, 5, 6, 7, 8, 9]

// 合并数组和单个值
const withValue = arr1.concat(10, 11);
console.log(withValue);  // [1, 2, 3, 10, 11]

// 现在写法(使用展开运算符)
const modernCombined = [...arr1, ...arr2];
console.log(modernCombined);  // [1, 2, 3, 4, 5, 6]

2. slice() - 提取子数组

const numbers = [10, 20, 30, 40, 50, 60, 70];

// slice(start, end) - 从start到end(不包括end)
const sub1 = numbers.slice(2, 5);
console.log(sub1);  // [30, 40, 50]

// 只指定起始位置
const sub2 = numbers.slice(3);
console.log(sub2);  // [40, 50, 60, 70]

// 负数索引
const sub3 = numbers.slice(-3);
console.log(sub3);  // [50, 60, 70]

// 复制整个数组
const copy = numbers.slice();
console.log(copy);  // [10, 20, 30, 40, 50, 60, 70]

3. splice() - 多功能操作

let months = ['一月', '二月', '三月', '四月', '五月', '六月'];
console.log('原始数组:', months);

// 删除元素
let removed = months.splice(2, 2);  // 从索引2删除2个元素
console.log('删除的元素:', removed);  // ['三月', '四月']
console.log('删除后:', months);  // ['一月', '二月', '五月', '六月']

// 插入元素
months.splice(2, 0, '三月', '四月');  // 在索引2插入,不删除
console.log('插入后:', months);  // ['一月', '二月', '三月', '四月', '五月', '六月']

// 替换元素
months.splice(3, 1, '四月(修订版)');
console.log('替换后:', months);  // ['一月', '二月', '三月', '四月(修订版)', '五月', '六月']

4. forEach() - 遍历数组

let users = [
    { name: '张三', age: 25 },
    { name: '李四', age: 30 },
    { name: '王五', age: 28 },
    { name: '赵六', age: 22 }
];

// 基本遍历
users.forEach(function(user, index) {
    console.log(`索引${index}: ${user.name},年龄${user.age}`);
});

// 使用箭头函数
users.forEach((user, index) => {
    console.log(`${user.name}明年就${user.age + 1}岁了`);
});

// 计算平均年龄
let totalAge = 0;
users.forEach(user => {
    totalAge += user.age;
});
console.log('平均年龄:', totalAge / users.length);

5. map() - 映射新数组

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

// 每个元素乘以2
const doubled = numbers.map(num => num * 2);
console.log(doubled);  // [2, 4, 6, 8, 10]

// 提取对象属性
const products = [
    { id: 1, name: '笔记本电脑', price: 5999 },
    { id: 2, name: '手机', price: 3299 },
    { id: 3, name: '平板', price: 2499 }
];

const productNames = products.map(product => product.name);
console.log(productNames);  // ['笔记本电脑', '手机', '平板']

// 格式化数据
const formattedProducts = products.map(product => ({
    ...product,
    price: `¥${product.price}`,
    inStock: true
}));
console.log(formattedProducts);

6. filter() - 过滤数组

const numbers = [12, 5, 8, 130, 44, 9, 33];

// 过滤出大于10的数
const filtered = numbers.filter(num => num > 10);
console.log(filtered);  // [12, 130, 44, 33]

// 过滤出偶数
const evens = numbers.filter(num => num % 2 === 0);
console.log(evens);  // [12, 8, 130, 44]

// 实际应用:筛选符合条件的用户
const users = [
    { name: '张三', age: 25, active: true },
    { name: '李四', age: 17, active: true },
    { name: '王五', age: 30, active: false },
    { name: '赵六', age: 19, active: true }
];

const actives = users.filter(user => user.active && user.age >= 18);
console.log(actives);
// [{ name: '张三', age: 25, active: true }, { name: '赵六', age: 19, active: true }]

7. reduce() - 归并计算

const numbers = [15, 25, 35, 45, 55];

// 计算总和
const sum = numbers.reduce((accumulator, currentValue) => {
    return accumulator + currentValue;
}, 0);
console.log('总和:', sum);  // 175

// 计算乘积
const product = numbers.reduce((acc, val) => acc * val, 1);
console.log('乘积:', product);  // 15*25*35*45*55 = 32484375

// 高级应用:统计出现次数
const fruits = ['苹果', '香蕉', '苹果', '橙子', '香蕉', '苹果', '葡萄'];
const fruitCount = fruits.reduce((count, fruit) => {
    count[fruit] = (count[fruit] || 0) + 1;
    return count;
}, {});

console.log(fruitCount);  // {苹果: 3, 香蕉: 2, 橙子: 1, 葡萄: 1}

8. find() 和 findIndex()

const users = [
    { id: 101, name: '张三', role: 'admin' },
    { id: 102, name: '李四', role: 'user' },
    { id: 103, name: '王五', role: 'user' },
    { id: 104, name: '赵六', role: 'moderator' }
];

// find() - 查找第一个匹配的元素
const admin = users.find(user => user.role === 'admin');
console.log(admin);  // { id: 101, name: '张三', role: 'admin' }

// findIndex() - 查找第一个匹配的索引
const userIndex = users.findIndex(user => user.name === '王五');
console.log(userIndex);  // 2

// 如果找不到,find返回undefined,findIndex返回-1
const notFound = users.find(user => user.name === '刘八');
console.log(notFound);  // undefined

9. some() 和 every()

const scores = [85, 90, 78, 92, 88];

// some() - 至少有一个满足条件
const hasHighScore = scores.some(score => score >= 90);
console.log('是否有90分以上?', hasHighScore);  // true

const hasPerfect = scores.some(score => score === 100);
console.log('是否有满分?', hasPerfect);  // false

// every() - 所有元素都满足条件
const allPass = scores.every(score => score >= 60);
console.log('是否都及格?', allPass);  // true

const allExcellent = scores.every(score => score >= 90);
console.log('是否都优秀?', allExcellent);  // false

10. includes() 和 indexOf()

const colors = ['红色', '蓝色', '绿色', '黄颜色', '蓝色'];

// includes() - 检查是否包含
console.log(colors.includes('绿色'));    // true
console.log(colors.includes('紫色'));    // false

// indexOf() - 查找第一次出现的索引
console.log(colors.indexOf('蓝色'));     // 1
console.log(colors.indexOf('蓝色', 2));  // 4(从索引2开始查找)

// lastIndexOf() - 查找之后一次出现的索引
console.log(colors.lastIndexOf('蓝色')); // 4
console.log(colors.lastIndexOf('紫色')); // -1

11. sort() - 排序

// 字符串排序
const fruits = ['香蕉', '苹果', '橙子', '葡萄', '草莓'];
fruits.sort();
console.log(fruits);  // ['苹果', '葡萄', '橙子', '草莓', '香蕉']

// 数字排序(需要提供比较函数)
const numbers = [45, 3, 27, 12, 8, 36, 19];

// 默认排序(按字符串排序,结果不符合预期)
numbers.sort();
console.log(numbers);  // [12, 19, 27, 3, 36, 45, 8]

// 正确的数字升序排序
numbers.sort((a, b) => a - b);
console.log('升序:', numbers);  // [3, 8, 12, 19, 27, 36, 45]

// 降序排序
numbers.sort((a, b) => b - a);
console.log('降序:', numbers);  // [45, 36, 27, 19, 12, 8, 3]

// 对象数组排序
const students = [
    { name: '张三', score: 85 },
    { name: '李四', score: 92 },
    { name: '王五', score: 78 },
    { name: '赵六', score: 96 }
];

// 按分数降序
students.sort((a, b) => b.score - a.score);
console.log(students);

12. reverse() - 反转数组

const letters = ['A', 'B', 'C', 'D', 'E'];
console.log('原始数组:', letters);

letters.reverse();
console.log('反转后:', letters);  // ['E', 'D', 'C', 'B', 'A']

// 实际应用:获取数组的之后几个元素(不修改原数组)
const numbers = [10, 20, 30, 40, 50, 60];
const lastThree = [...numbers].reverse().slice(0, 3).reverse();
console.log(lastThree);  // [40, 50, 60]

13. join() - 数组转字符串

const words = ['Hello', 'World', 'JavaScript', 'is', 'awesome'];

// 默认用逗号连接
console.log(words.join());  // 'Hello,World,JavaScript,is,awesome'

// 指定连接符
console.log(words.join(' '));   // 'Hello World JavaScript is awesome'
console.log(words.join('-'));   // 'Hello-World-JavaScript-is-awesome'
console.log(words.join(''));    // 'HelloWorldJavaScriptisawesome'

// 实际应用:URL参数拼接
const params = {
    page: 1,
    limit: 10,
    keyword: 'javascript'
};

const queryString = Object.entries(params)
    .map(([key, value]) => `${key}=${encodeURIComponent(value)}`)
    .join('&');

console.log(queryString);  // 'page=1&limit=10&keyword=javascript'

14. flat() 和 flatMap()

// flat() - 扁平化数组
const nestedArray = [1, [2, 3], [4, [5, 6]]];

// 默认扁平化一层
const flat1 = nestedArray.flat();
console.log(flat1);  // [1, 2, 3, 4, [5, 6]]

// 指定扁平化深度
const flat2 = nestedArray.flat(2);
console.log(flat2);  // [1, 2, 3, 4, 5, 6]

// flatMap() - 映射并扁平化
const sentences = ['Hello world', 'JavaScript is fun', 'I love coding'];

const words = sentences.flatMap(sentence => sentence.split(' '));
console.log(words);
// ['Hello', 'world', 'JavaScript', 'is', 'fun', 'I', 'love', 'coding']

15. 静态方法:Array.isArray()

console.log(Array.isArray([1, 2, 3]));      // true
console.log(Array.isArray({}));              // false
console.log(Array.isArray('hello'));         // false
console.log(Array.isArray(null));            // false
console.log(Array.isArray(undefined));       // false

// 实际应用:安全的数组操作
function processData(data) {
    if (!Array.isArray(data)) {
        console.log('输入不是数组,转为数组');
        data = [data];
    }
    return data.map(item => item * 2);
}

console.log(processData([1, 2, 3]));  // [2, 4, 6]
console.log(processData(5));           // [10](自动转为数组)

数组遍历方式对比

const fruits = ['苹果', '香蕉', '橙子', '葡萄'];

// 1. for循环(性能很好)
console.log('=== for循环 ===');
for (let i = 0; i < fruits.length; i++) {
    console.log(`索引${i}: ${fruits[i]}`);
}

// 2. for...of(遍历值)
console.log('=== for...of ===');
for (let fruit of fruits) {
    console.log(fruit);
}

// 3. for...in(遍历索引,不推荐用于数组)
console.log('=== for...in ===');
for (let index in fruits) {
    console.log(`索引${index}: ${fruits[index]}`);
}

// 4. forEach(函数式)
console.log('=== forEach ===');
fruits.forEach((fruit, index) => {
    console.log(`索引${index}: ${fruit}`);
});

// 5. map(返回新数组)
console.log('=== map ===');
const upperFruits = fruits.map(fruit => fruit.toUpperCase());
console.log(upperFruits);

课程知识要点

  1. 数组定义:有序的数据,通过索引访问,索引从0开始

  2. 创建方式:字面量[]、new Array()、Array.of()、Array.from()

  3. 增删操作:push/pop(末尾)、unshift/shift(开头)、splice(任意位置)

  4. 遍历方法:for、forEach、for...of、map、filter

  5. 查找方法:indexOf、lastIndexOf、find、findIndex、includes

  6. 判断方法:some、every、isArray

  7. 转换方法:map、filter、reduce、flat、flatMap

  8. 排序方法:sort、reverse

  9. 合并拆分:concat、slice、join

  10. 静态方法:Array.isArray()、Array.from()、Array.of()

开发实践建议

基于多年JavaScript开发经验,我对数组使用的建议如下:

常用组合模式:

// 链式调用示例
const products = [
    { name: '笔记本', price: 5999, category: '电子产品' },
    { name: 'T恤', price: 99, category: '服装' },
    { name: '手机', price: 3299, category: '电子产品' },
    { name: '裤子', price: 199, category: '服装' },
    { name: '平板', price: 2499, category: '电子产品' }
];

// 获取所有电子产品的名称,按价格排序
const electronicsNames = products
    .filter(product => product.category === '电子产品')
    .sort((a, b) => a.price - b.price)
    .map(product => product.name);

console.log(electronicsNames);  // ['平板', '手机', '笔记本']

性能考虑:

  • 大量数据时,传统for循环性能较优

  • 函数式方法(map/filter/reduce)代码更清晰,适合大多数场景

  • 避免在循环中修改数组长度

常见:

// 1. 数组是引用类型
let arr1 = [1, 2, 3];
let arr2 = arr1;  // 不是复制,是引用
arr2.push(4);
console.log(arr1);  // [1, 2, 3, 4](原数组被修改)

// 正确复制方式
let arr3 = [...arr1];
let arr4 = arr1.slice();

// 2. 使用delete删除元素(留下空位)
let colors = ['红', '绿', '蓝'];
delete colors[1];
console.log(colors);  // ['红', empty, '蓝']
console.log(colors.length);  // 3(仍然3)

// 正确方式:使用splice
colors.splice(1, 1);
console.log(colors);  // ['红', '蓝']

// 3. sort默认按字符串排序
let nums = [10, 2, 30, 4];
nums.sort();
console.log(nums);  // [10, 2, 30, 4](不是数值排序)

// 正确方式:提供比较函数
nums.sort((a, b) => a - b);
console.log(nums);  // [2, 4, 10, 30]

数组是JavaScript中最灵活、强大的数据结构之一。掌握这些方法和技巧,能够让你在处理数据时更加得心应手,写出更简洁高效的代码。

← JavaScript对象 没有下一篇了 →
分享笔记 (共有 篇笔记)
验证码:
微信公众号