TypeScript 循环语句详解
TypeScript 的循环语句语法与 JavaScript 完全相同,包括 for、for...of、for...in、while、do...while,以及数组的高阶方法(如 forEach、map 等)。TypeScript 的优势在于类型推断和类型检查,能确保循环中变量的类型安全,尤其在遍历数组、对象或联合类型时。
1. for 循环(经典三段式)
语法:
for (let i = 0; i < length; i++) {
// 代码
}
示例:
for (let i: number = 0; i < 5; i++) {
console.log(`第 ${i + 1} 次循环`);
}
// TS 会自动推断 i 为 number,无需显式注解
for (let i = 0; i < 5; i++) {
console.log(i * 2);
}
2. for…of 循环(遍历可迭代对象的值)
最常用在数组、字符串、Set、Map 等可迭代对象上。
const colors: string[] = ["red", "green", "blue"];
for (const color of colors) {
// color 类型被推断为 string
console.log(color.toUpperCase()); // 安全调用字符串方法
}
const str: string = "TypeScript";
for (const char of str) {
console.log(char); // char 类型为 string
}
优势:简洁、安全,推荐用于数组遍历。
3. for…in 循环(遍历对象的键)
遍历对象的可枚举属性键(包括原型链上的)。
interface User {
name: string;
age: number;
}
const user: User = { name: "Alice", age: 25 };
for (const key in user) {
// key 类型被推断为 keyof User,即 "name" | "age"
console.log(`${key}: ${user[key]}`);
}
// 注意:for...in 会遍历原型链,实际使用时常结合 hasOwnProperty 检查
for (const key in user) {
if (Object.hasOwnProperty.call(user, key)) {
console.log(user[key as keyof User]);
}
}
注意:不推荐用于数组遍历(会遍历索引作为字符串,可能导致意外)。
4. while 循环
let count: number = 0;
while (count < 5) {
console.log(count);
count++;
}
5. do…while 循环(至少执行一次)
let input: string = "";
do {
input = prompt("请输入 quit 退出") || ""; // 假设浏览器环境
} while (input !== "quit");
console.log("已退出");
6. 数组高阶方法(推荐在 TS 中优先使用)
这些方法类型安全,且代码更函数式、更易读。
| 方法 | 用途 | 返回值 | 示例 |
|---|---|---|---|
forEach | 遍历,无返回值 | void | arr.forEach(item => console.log(item)); |
map | 转换数组 | 新数组 | arr.map(x => x * 2); |
filter | 过滤 | 新数组 | arr.filter(x => x > 10); |
find | 查找第一个匹配元素 | 元素或 undefined | arr.find(x => x > 10); |
some | 是否存在匹配 | boolean | arr.some(x => x > 10); |
every | 是否全部匹配 | boolean | arr.every(x => x > 0); |
reduce | 归约(累加、汇总) | 任意类型 | arr.reduce((sum, x) => sum + x, 0); |
TS 类型优势示例:
const numbers: number[] = [1, 2, 3, 4, 5];
// map 返回类型自动推断为 number[]
const doubled: number[] = numbers.map(n => n * 2);
// filter 返回类型仍为 number[]
const evens: number[] = numbers.filter(n => n % 2 === 0);
// reduce 可指定累加器类型
const sum: number = numbers.reduce((acc: number, curr) => acc + curr, 0);
7. 循环控制语句
| 语句 | 作用 | 示例 |
|---|---|---|
break | 跳出当前循环 | break; |
continue | 跳过本次循环,继续下一次 | continue; |
label | 为循环命名,可跳出外层循环 |
带标签的 break(用于嵌套循环):
outer: for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (i === 1 && j === 1) {
break outer; // 直接跳出外层循环
}
console.log(i, j);
}
}
8. 最佳实践建议
- 优先使用
for...of遍历数组,简洁且类型安全。 - 避免
for...in用于数组。 - 大规模数据处理优先使用高阶方法(
map、filter等),更符合函数式编程。 - 避免无限循环:TS 无法完全检测,但逻辑上要确保退出条件。
- 结合类型守卫在循环中缩小类型:
const items: (string | number)[] = ["a", 1, "b", 2];
for (const item of items) {
if (typeof item === "string") {
// item 被缩小为 string
console.log(item.toUpperCase());
} else {
// item 被缩小为 number
console.log(item.toFixed());
}
}
小结:循环方式速查
| 场景 | 推荐方式 | 原因 |
|---|---|---|
| 遍历数组值 | for...of 或 forEach/map | 类型安全、简洁 |
| 遍历对象属性 | for...in 或 Object.keys() | 获取键 |
| 需要索引 | 经典 for (let i = 0; ...) | 可访问 i |
| 条件不确定次数 | while / do...while | 灵活 |
| 函数式转换/过滤 | map、filter、reduce | 不可变、更易测试 |
如果您想看实际应用示例(如遍历 Map/Set、异步循环结合 async/await、或性能对比),请告诉我!