javascript 数组(千字长文)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;演示链接: http://116.62.199.48:7070 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 90w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3100+ 小伙伴加入学习 ,欢迎点击围观
在 JavaScript 开发中,数组(Array)是处理数据的核心工具之一。无论是处理用户输入、操作 DOM 节点,还是构建复杂的数据结构,数组都扮演着不可替代的角色。对于编程初学者而言,理解数组的特性与常用方法是迈向进阶开发的关键一步;而中级开发者则可以通过深入掌握其底层原理与高级技巧,进一步提升代码的效率与可维护性。本文将从基础到进阶,系统性地解析 JavaScript 数组的各个方面,并通过实际案例帮助读者巩固知识。
一、数组的基础概念与创建方式
1.1 什么是 JavaScript 数组?
JavaScript 数组是一个有序的集合,可以存储多个值,并通过索引(index)快速访问这些值。想象一个书架上的书,每本书的位置由编号确定,数组中的元素也类似,每个元素都有一个从 0
开始递增的索引。例如:
const books = ["JavaScript权威指南", "算法图解", "设计模式"];
console.log(books[0]); // 输出:"JavaScript权威指南"
这里 books
就是一个数组,books[0]
表示第一个元素。
1.2 创建数组的多种方式
JavaScript 提供了多种创建数组的方法:
- 直接赋值法:
const fruits = ["apple", "banana", "orange"];
- 构造函数法:
const numbers = new Array(3); // 创建长度为3的空数组 numbers[0] = 10; // 需要手动赋值
- 动态生成法:
const evenNumbers = Array.from({ length: 5 }, (_, index) => (index + 1) * 2); // 输出:[2, 4, 6, 8, 10]
这里
Array.from()
结合映射函数,可以高效生成特定模式的数组。
二、数组的常用操作方法
2.1 增删改查的核心方法
增:push()、unshift()
push()
在数组末尾添加元素:let arr = [1, 2]; arr.push(3); // arr 变为 [1,2,3]
unshift()
在数组开头添加元素:arr.unshift(0); // arr 变为 [0,1,2,3]
删:pop()、shift()
pop()
删除末尾元素:arr.pop(); // 删除3后,arr 变为 [0,1,2]
shift()
删除开头元素:arr.shift(); // 删除0后,arr 变为 [1,2]
改:通过索引直接赋值
arr[0] = 100; // arr 变为 [100,2]
查:通过索引或方法遍历
for (let i = 0; i < arr.length; i++) {
console.log(arr[i]); // 逐个输出元素
}
2.2 高级遍历与转换方法
map():转换数组元素
map()
方法会遍历数组中的每个元素,返回一个新数组,适合数据格式化场景:
const prices = [19.9, 29.9, 39.9];
const taxedPrices = prices.map(price => price * 1.08);
// taxedPrices 结果:[21.492, 32.292, 43.092]
filter():筛选符合条件的元素
const evenNumbers = [1,2,3,4,5].filter(num => num % 2 === 0);
// evenNumbers 结果:[2,4]
reduce():聚合数据
reduce()
可以将数组元素“缩减”为单一值,常用于求和、统计等场景:
const sum = [1,2,3,4,5].reduce((total, num) => total + num, 0);
// sum 结果:15
find() 与 findIndex():精准查找
const users = [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" }
];
const foundUser = users.find(user => user.name === "Bob");
// foundUser 结果:{ id:2, name:"Bob" }
三、数组的高级特性与性能优化
3.1 数组的可变性与不可变性
JavaScript 数组是**可变(mutable)**的,这意味着修改数组会直接改变原始数据。例如:
let arr = [1,2,3];
arr.push(4); // 原数组被修改
但在函数式编程中,推荐使用不可变方法(如 map()
返回新数组),避免副作用:
const newArr = [...arr, 4]; // 使用扩展运算符创建新数组
3.2 浅拷贝与深拷贝的陷阱
直接赋值 =
或扩展运算符 ...
会创建浅拷贝,即对象元素仍指向同一内存地址:
const arr1 = [{ name: "A" }];
const arr2 = [...arr1];
arr2[0].name = "B";
console.log(arr1[0].name); // 输出:"B"(因为引用未变)
要实现深拷贝,可以使用 JSON.parse(JSON.stringify(...))
或第三方库:
const deepCopy = JSON.parse(JSON.stringify(arr1));
3.3 ES6 新特性:展开运算符与解构赋值
展开运算符(...)
const combined = [1,2, ...[3,4], 5]; // 合并数组
// combined 结果:[1,2,3,4,5]
解构赋值
快速提取数组元素:
const [first, second] = [10, 20];
console.log(first); // 10
四、常见问题与解决方案
4.1 数组去重
传统方法使用 filter()
:
const unique = arr => arr.filter((item, index) => arr.indexOf(item) === index);
ES6 方法更简洁:
const uniqueES6 = [...new Set([1,2,2,3])]; // 结果:[1,2,3]
4.2 合并两个数组
const merged = arr1.concat(arr2); // 或使用扩展运算符 [...arr1, ...arr2]
4.3 判断是否为数组
避免使用 instanceof
,改用 Array.isArray()
:
Array.isArray([]); // true
五、实战案例:构建一个购物车系统
5.1 需求分析
假设需要实现一个购物车,支持添加、删除商品,并计算总价。
5.2 代码实现
class ShoppingCart {
constructor() {
this.items = [];
}
addItem(item) {
this.items.push(item);
}
removeItem(index) {
this.items.splice(index, 1);
}
calculateTotal() {
return this.items.reduce((total, item) => total + item.price, 0);
}
}
// 使用示例
const cart = new ShoppingCart();
cart.addItem({ name: "Coffee", price: 3.5 });
console.log(cart.calculateTotal()); // 3.5
六、总结
JavaScript 数组作为开发中高频使用的数据结构,其灵活性与强大性往往被低估。从基础的增删改查到高级的函数式编程技巧,掌握数组的特性能够显著提升代码质量与开发效率。对于初学者,建议从简单操作入手,逐步结合实际项目练习;中级开发者则可以深入研究性能优化与设计模式,例如结合数组实现队列、栈等抽象数据类型。通过持续实践,数组将成为你手中得心应手的工具,助力解决各类编程挑战。
通过本文的讲解,希望读者能够系统性地理解 JavaScript 数组的使用场景与核心技巧。在后续学习中,建议结合 MDN 文档与开源项目,进一步探索数组的更多可能性。