TypeScript 循环(手把手讲解)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观
在编程的世界中,循环是解决问题的核心工具之一。无论是遍历数组、处理数据流,还是构建复杂的逻辑结构,循环都像一座桥梁,连接着代码的简洁性和功能的多样性。在 TypeScript 中,循环不仅继承了 JavaScript 的灵活性,还通过类型系统为开发者提供了更安全的编码体验。本文将从基础到进阶,系统讲解 TypeScript 循环的语法、应用场景和最佳实践,帮助读者在实际开发中高效利用这一工具。
一、TypeScript 循环的语法基础
1.1 基础循环:for 循环
for 循环是最经典的循环结构,它通过初始化、条件判断和迭代三部分实现循环逻辑。
// 示例:计算 1 到 10 的和
let sum = 0;
for (let i = 1; i <= 10; i++) {
sum += i;
}
console.log(sum); // 输出 55
比喻:可以将 for 循环想象成一个“交通灯系统”:
- 初始化(
let i = 1
):相当于绿灯亮起,车辆开始行驶。 - 条件判断(
i <= 10
):红灯检查是否需要停止。 - 迭代(
i++
):车辆前进一格,准备下一轮循环。
1.2 while 和 do-while 循环
while 循环和 do-while 循环的区别在于执行顺序:
// while 循环:先判断条件再执行
let count = 0;
while (count < 3) {
console.log("循环中");
count++;
}
// do-while 循环:先执行一次,再判断条件
let attempt = 0;
do {
console.log("至少执行一次");
attempt++;
} while (attempt < 1); // 即使初始条件不满足,也会执行一次
比喻:
- while 像一个“守门人”,只有符合条件才会放行。
- do-while 则像一个“试吃活动”,先让客人尝一口,再决定是否继续。
二、TypeScript 循环的进阶用法
2.1 数组遍历:forEach 和 for...of
forEach 是数组的高阶函数,适合简单的遍历操作:
const numbers = [1, 2, 3];
numbers.forEach((num) => {
console.log(num * 2); // 输出 2, 4, 6
});
for...of 则更简洁,直接获取元素值:
for (const num of numbers) {
console.log(num); // 输出 1, 2, 3
}
对比:
| 方法 | 语法特点 | 适用场景 |
|---------------|---------------------------|------------------------------|
| forEach | 需要提供回调函数 | 简单遍历,无返回值 |
| for...of | 直接访问元素值 | 需要更灵活的操作(如修改变量)|
2.2 对象遍历:for...in 和键值对操作
for...in 循环用于遍历对象的可枚举属性:
const person = { name: "Alice", age: 30 };
for (const key in person) {
console.log(`${key}: ${person[key]}`); // 输出 "name: Alice" 和 "age: 30"
}
注意:
- 遍历时获取的是属性名(如
key
),而非属性值。 - 如果需要同时获取键和值,可以结合
Object.entries()
:for (const [key, value] of Object.entries(person)) { console.log(`键:${key}, 值:${value}`); }
2.3 类数组和迭代器:Array.from() 和 Symbol.iterator
对于类数组对象(如 arguments
),可以通过 Array.from()
转换后遍历:
function logArgs() {
const argsArray = Array.from(arguments);
argsArray.forEach((arg) => console.log(arg));
}
logArgs("a", "b", "c"); // 输出 a, b, c
Symbol.iterator 则允许自定义对象的迭代逻辑:
class MyIterable {
*[Symbol.iterator]() {
yield 1;
yield 2;
yield 3;
}
}
const iter = new MyIterable();
for (const num of iter) {
console.log(num); // 输出 1, 2, 3
}
三、TypeScript 循环的类型安全与最佳实践
3.1 类型推断与显式类型
TypeScript 的类型系统能自动推断循环变量的类型,但显式声明可以避免歧义:
const items: { id: number; name: string }[] = [
{ id: 1, name: "Apple" },
{ id: 2, name: "Banana" },
];
for (const item of items) {
console.log(item.name); // 类型推断为 { id: number; name: string }
}
3.2 避免无限循环
循环的终止条件必须合理,否则可能导致程序崩溃:
// 错误示例:无限循环
let i = 0;
while (i < 5) {
console.log(i); // 永远输出 0
}
// 修复:添加迭代语句
while (i < 5) {
console.log(i);
i++; // 必不可少!
}
3.3 性能优化:减少嵌套循环
嵌套循环会显著降低性能,可通过以下方式优化:
// 低效写法
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr.length; j++) {
// 复杂计算
}
}
// 优化:缓存 arr.length
const len = arr.length;
for (let i = 0; i < len; i++) {
// ...
}
四、实战案例:TypeScript 循环的综合应用
4.1 过滤数组并生成新数组
interface Product {
id: number;
price: number;
inStock: boolean;
}
const products: Product[] = [
{ id: 1, price: 100, inStock: true },
{ id: 2, price: 50, inStock: false },
];
// 使用 map() 过滤并计算总价
const filteredProducts = products
.filter(p => p.inStock)
.map(p => ({ ...p, total: p.price * 2 }));
console.log(filteredProducts); // 输出包含符合条件的元素和总价
4.2 对象属性的动态遍历
function logProperties(obj: object) {
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
console.log(`属性 ${key} 的值是:${obj[key]}`);
}
}
}
logProperties({ a: 1, b: "text" });
结论
通过本文的讲解,我们深入理解了 TypeScript 循环的语法、类型安全特性及实际应用场景。无论是基础的 for 循环、高效的数组遍历,还是复杂的对象迭代,掌握这些技巧能显著提升代码的健壮性和可维护性。在开发中,合理选择循环结构、遵循类型安全规范,并结合实际案例优化性能,将帮助开发者在 TypeScript 生态中游刃有余。
记住:循环不是终点,而是实现复杂逻辑的起点。通过不断实践,你将发现 TypeScript 循环能为你的代码注入无限可能!