for循环
2025年3月7日大约 6 分钟
for循环
for循环是JavaScript中最常用的循环结构之一。本文将介绍for循环的语法、变体和常见用法。
基本语法
for循环的基本语法如下:
for (初始化; 条件; 更新) {
// 循环体
}
其中:
- 初始化:在循环开始前执行一次,通常用于初始化计数器变量
- 条件:在每次循环迭代前检查,如果为true则执行循环体,否则退出循环
- 更新:在每次循环体执行后执行,通常用于更新计数器变量
示例
// 打印1到5的数字
for (let i = 1; i <= 5; i++) {
console.log(i);
}
// 输出: 1, 2, 3, 4, 5
for循环的执行流程
- 执行初始化表达式(仅执行一次)
- 检查条件表达式
- 如果为
true
,执行循环体 - 如果为
false
,退出循环
- 如果为
- 执行循环体
- 执行更新表达式
- 返回步骤2
for循环的变体
多个初始化或更新表达式
可以使用逗号运算符在初始化和更新部分包含多个表达式:
for (let i = 0, j = 10; i < j; i++, j--) {
console.log(i, j);
}
// 输出: 0 10, 1 9, 2 8, 3 7, 4 6
省略部分表达式
for循环的三个表达式部分都是可选的:
// 省略初始化(在循环外初始化)
let i = 0;
for (; i < 5; i++) {
console.log(i);
}
// 省略条件(需要在循环体内使用break避免无限循环)
for (let i = 0; ; i++) {
if (i >= 5) break;
console.log(i);
}
// 省略更新(在循环体内更新)
for (let i = 0; i < 5;) {
console.log(i);
i++;
}
// 省略所有表达式(创建无限循环)
// for (;;) {
// // 无限循环,需要使用break退出
// }
for...in循环
for...in
循环用于遍历对象的可枚举属性:
const person = {
name: '张三',
age: 30,
job: '工程师'
};
for (let key in person) {
console.log(`${key}: ${person[key]}`);
}
// 输出:
// name: 张三
// age: 30
// job: 工程师
注意事项:
for...in
循环也会遍历原型链上的可枚举属性- 不建议用于遍历数组,因为顺序不保证,且会遍历数组的其他属性
- 如果只想遍历对象自身的属性,可以使用
hasOwnProperty()
方法
for (let key in person) {
if (person.hasOwnProperty(key)) {
console.log(`${key}: ${person[key]}`);
}
}
for...of循环
ES6引入的for...of
循环用于遍历可迭代对象(如数组、字符串、Map、Set等):
// 遍历数组
const colors = ['红', '绿', '蓝'];
for (let color of colors) {
console.log(color);
}
// 输出: 红, 绿, 蓝
// 遍历字符串
const str = 'Hello';
for (let char of str) {
console.log(char);
}
// 输出: H, e, l, l, o
// 遍历Map
const map = new Map([
['name', '李四'],
['age', 25]
]);
for (let [key, value] of map) {
console.log(`${key}: ${value}`);
}
// 输出:
// name: 李四
// age: 25
for...of
与for...in
的区别:
for...in
遍历对象的可枚举属性键for...of
遍历可迭代对象的值for...of
不能直接遍历普通对象(除非实现了迭代器)
常见用法和技巧
遍历数组
const fruits = ['苹果', '香蕉', '橙子'];
// 使用索引
for (let i = 0; i < fruits.length; i++) {
console.log(`索引 ${i}: ${fruits[i]}`);
}
// 使用for...of(推荐)
for (let fruit of fruits) {
console.log(fruit);
}
// 使用forEach方法(函数式方法)
fruits.forEach((fruit, index) => {
console.log(`索引 ${index}: ${fruit}`);
});
反向遍历
const numbers = [1, 2, 3, 4, 5];
// 从后向前遍历
for (let i = numbers.length - 1; i >= 0; i--) {
console.log(numbers[i]);
}
// 输出: 5, 4, 3, 2, 1
跳过或终止迭代
// 使用continue跳过当前迭代
for (let i = 1; i <= 10; i++) {
if (i % 2 === 0) {
continue; // 跳过偶数
}
console.log(i);
}
// 输出: 1, 3, 5, 7, 9
// 使用break终止循环
for (let i = 1; i <= 10; i++) {
if (i > 5) {
break; // 当i大于5时终止循环
}
console.log(i);
}
// 输出: 1, 2, 3, 4, 5
嵌套循环
// 生成乘法表
for (let i = 1; i <= 9; i++) {
let row = '';
for (let j = 1; j <= i; j++) {
row += `${j}×${i}=${j*i}\t`;
}
console.log(row);
}
使用标签语句
标签语句可以与break
和continue
一起使用,控制外层循环:
outerLoop: for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (i === 1 && j === 1) {
break outerLoop; // 跳出外层循环
}
console.log(`i=${i}, j=${j}`);
}
}
// 输出:
// i=0, j=0
// i=0, j=1
// i=0, j=2
// i=1, j=0
性能考虑
缓存数组长度
在遍历大型数组时,缓存数组长度可以提高性能:
// 不推荐(每次迭代都会计算length)
for (let i = 0; i < array.length; i++) {
// 循环体
}
// 推荐(只计算一次length)
for (let i = 0, len = array.length; i < len; i++) {
// 循环体
}
避免在循环中修改数组长度
在循环中修改数组长度可能导致意外行为:
const numbers = [1, 2, 3, 4, 5];
// 不推荐
for (let i = 0; i < numbers.length; i++) {
if (numbers[i] % 2 === 0) {
numbers.splice(i, 1); // 这会改变数组长度和索引
i--; // 需要调整索引
}
}
// 推荐:使用过滤创建新数组
const oddNumbers = numbers.filter(num => num % 2 !== 0);
现代替代方案
现代JavaScript提供了许多函数式方法来替代传统的for循环:
const numbers = [1, 2, 3, 4, 5];
// map:转换数组元素
const doubled = numbers.map(num => num * 2);
// 结果: [2, 4, 6, 8, 10]
// filter:过滤数组元素
const evens = numbers.filter(num => num % 2 === 0);
// 结果: [2, 4]
// reduce:将数组归约为单个值
const sum = numbers.reduce((total, num) => total + num, 0);
// 结果: 15
// find:查找满足条件的第一个元素
const firstEven = numbers.find(num => num % 2 === 0);
// 结果: 2
// some:检查是否至少有一个元素满足条件
const hasEven = numbers.some(num => num % 2 === 0);
// 结果: true
// every:检查是否所有元素都满足条件
const allPositive = numbers.every(num => num > 0);
// 结果: true
总结
for循环是JavaScript中强大而灵活的循环结构,有多种变体和用法:
- 标准
for
循环适用于需要精确控制迭代过程的场景 for...in
循环适用于遍历对象属性for...of
循环适用于遍历可迭代对象的值- 现代JavaScript提供了许多函数式方法作为循环的替代方案
选择合适的循环结构取决于具体的使用场景和个人偏好。在处理集合数据时,现代的函数式方法通常更加简洁和易读,而传统的for循环在需要精细控制时仍然非常有用。
练习
- 使用for循环计算1到100的和
- 使用for...of循环遍历字符串,统计元音字母的数量
- 使用嵌套for循环生成一个10x10的乘法表
- 使用for循环和continue语句打印1到20之间的所有奇数
- 使用for...in循环遍历一个对象,并过滤出只属于对象自身的属性