JavaScript 循环语句
循环语句是编程语言中的重要控制结构,用于重复执行一段代码直到满足特定条件。在 JavaScript 中,循环语句可以帮助我们高效地处理数组、对象和其他数据集合。掌握循环语句对于编写高效的 JavaScript 程序至关重要。在本章节中,我们将深入学习 JavaScript 中的各种循环语句。
循环语句的基本概念
循环语句允许我们重复执行代码块,避免重复编写相同的代码。JavaScript 提供了多种循环语句:
- for 循环
- while 循环
- do...while 循环
- for...in 循环
- for...of 循环
for 循环
for 循环是最常用的循环语句之一,适用于已知循环次数的情况。
基本语法
javascript
for (初始化; 条件; 更新) {
// 循环体
}示例
javascript
// 打印数字 1 到 5
for (let i = 1; i <= 5; i++) {
console.log(i);
}
// 计算 1 到 10 的和
let sum = 0;
for (let i = 1; i <= 10; i++) {
sum += i;
}
console.log("1到10的和:" + sum); // 55for 循环的组成部分
- 初始化:循环开始前执行一次
- 条件:每次循环前检查,为 true 时继续循环
- 更新:每次循环后执行
倒序循环
javascript
// 从 10 倒数到 1
for (let i = 10; i >= 1; i--) {
console.log(i);
}嵌套 for 循环
javascript
// 打印乘法表
for (let i = 1; i <= 9; i++) {
for (let j = 1; j <= 9; j++) {
console.log(i + " × " + j + " = " + (i * j));
}
console.log("---");
}while 循环
while 循环在条件为 true 时重复执行代码块。
基本语法
javascript
while (条件) {
// 循环体
}示例
javascript
// 打印数字 1 到 5
let i = 1;
while (i <= 5) {
console.log(i);
i++;
}
// 计算数字的位数
let number = 12345;
let count = 0;
let temp = number;
while (temp > 0) {
count++;
temp = Math.floor(temp / 10);
}
console.log(number + " 有 " + count + " 位数");do...while 循环
do...while 循环至少执行一次循环体,然后在条件为 true 时继续执行。
基本语法
javascript
do {
// 循环体
} while (条件);示例
javascript
// 至少执行一次
let i = 1;
do {
console.log(i);
i++;
} while (i <= 5);
// 用户输入验证示例
let userInput;
do {
userInput = prompt("请输入 'yes' 或 'no':");
} while (userInput !== "yes" && userInput !== "no");for...in 循环
for...in 循环用于遍历对象的可枚举属性。
基本语法
javascript
for (变量 in 对象) {
// 循环体
}示例
javascript
const person = {
name: "张三",
age: 25,
city: "北京"
};
// 遍历对象属性
for (let key in person) {
console.log(key + ": " + person[key]);
}
// 输出:
// name: 张三
// age: 25
// city: 北京
// 遍历数组(不推荐)
const colors = ["红", "绿", "蓝"];
for (let index in colors) {
console.log(index + ": " + colors[index]);
}
// 输出:
// 0: 红
// 1: 绿
// 2: 蓝for...of 循环
for...of 循环用于遍历可迭代对象(如数组、字符串、Map、Set 等)。
基本语法
javascript
for (变量 of 可迭代对象) {
// 循环体
}示例
javascript
// 遍历数组
const fruits = ["苹果", "香蕉", "橙子"];
for (let fruit of fruits) {
console.log(fruit);
}
// 输出:
// 苹果
// 香蕉
// 橙子
// 遍历字符串
const message = "Hello";
for (let char of message) {
console.log(char);
}
// 输出:
// H
// e
// l
// l
// o
// 遍历 Set
const uniqueNumbers = new Set([1, 2, 3, 4, 5]);
for (let num of uniqueNumbers) {
console.log(num);
}
// 遍历 Map
const userMap = new Map([
["name", "张三"],
["age", 25],
["city", "北京"]
]);
for (let [key, value] of userMap) {
console.log(key + ": " + value);
}循环控制语句
break 语句
break 语句用于立即退出循环。
javascript
// 在数组中查找特定元素
const numbers = [1, 3, 5, 7, 9, 11, 13];
let target = 7;
let found = false;
for (let i = 0; i < numbers.length; i++) {
if (numbers[i] === target) {
console.log("找到了 " + target + ",位置:" + i);
found = true;
break; // 找到后立即退出循环
}
}
if (!found) {
console.log("未找到 " + target);
}continue 语句
continue 语句用于跳过当前循环的剩余部分,直接进入下一次循环。
javascript
// 打印 1 到 10 中的偶数
for (let i = 1; i <= 10; i++) {
if (i % 2 !== 0) {
continue; // 跳过奇数
}
console.log(i);
}
// 输出:2, 4, 6, 8, 10
// 处理数组中的有效数据
const data = [1, null, 3, undefined, 5, 0, 7];
let sum = 0;
for (let value of data) {
if (value === null || value === undefined || value === 0) {
continue; // 跳过无效数据
}
sum += value;
}
console.log("有效数据的和:" + sum); // 16标签语句
标签语句可以与 break 和 continue 配合使用,控制嵌套循环。
javascript
// 使用标签跳出外层循环
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=" + i + ", j=" + j);
}
}
// 输出:
// i=0, j=0
// i=0, j=1
// i=0, j=2
// i=1, j=0
// 使用标签跳过外层循环的某次迭代
outer2: for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (i === 1 && j === 1) {
continue outer2; // 跳过外层循环的当前迭代
}
console.log("i=" + i + ", j=" + j);
}
}
// 输出:
// i=0, j=0
// i=0, j=1
// i=0, j=2
// i=1, j=0
// i=2, j=0
// i=2, j=1
// i=2, j=2循环的性能考虑
1. 缓存数组长度
javascript
const arr = [1, 2, 3, 4, 5];
// 不好的做法(每次循环都计算长度)
for (let i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
// 好的做法(缓存长度)
for (let i = 0, len = arr.length; i < len; i++) {
console.log(arr[i]);
}2. 倒序循环优化
javascript
const arr = [1, 2, 3, 4, 5];
// 倒序循环(避免每次比较长度)
for (let i = arr.length - 1; i >= 0; i--) {
console.log(arr[i]);
}不同循环的适用场景
1. for 循环
适用于:
- 已知循环次数
- 需要精确控制循环过程
- 数组索引操作
javascript
// 处理数组元素
for (let i = 0; i < array.length; i++) {
process(array[i], i);
}2. while 循环
适用于:
- 循环次数未知
- 基于条件的循环
javascript
// 读取数据直到结束
let data = readData();
while (data !== null) {
processData(data);
data = readData();
}3. do...while 循环
适用于:
- 至少执行一次的循环
javascript
// 用户菜单选择
let choice;
do {
choice = showMenu();
handleChoice(choice);
} while (choice !== "exit");4. for...in 循环
适用于:
- 遍历对象属性
javascript
// 遍历对象
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
console.log(key + ": " + obj[key]);
}
}5. for...of 循环
适用于:
- 遍历可迭代对象
- 不需要索引的数组遍历
javascript
// 遍历数组元素
for (let item of array) {
console.log(item);
}
// 遍历字符串字符
for (let char of string) {
console.log(char);
}循环的最佳实践
1. 选择合适的循环类型
javascript
// 遍历数组元素 - 推荐使用 for...of
const numbers = [1, 2, 3, 4, 5];
for (let num of numbers) {
console.log(num);
}
// 遍历数组元素和索引 - 使用 for 循环
for (let i = 0; i < numbers.length; i++) {
console.log(i + ": " + numbers[i]);
}
// 遍历对象属性 - 使用 for...in
const person = { name: "张三", age: 25 };
for (let key in person) {
if (person.hasOwnProperty(key)) {
console.log(key + ": " + person[key]);
}
}2. 避免无限循环
javascript
// 确保循环条件会改变
let i = 0;
while (i < 10) {
console.log(i);
i++; // 必须更新循环变量
}
// 使用 break 防止意外的无限循环
let attempts = 0;
while (condition) {
// 执行操作
attempts++;
// 防止无限循环
if (attempts > 1000) {
console.log("达到最大尝试次数");
break;
}
}3. 合理使用 break 和 continue
javascript
// 数据验证示例
function processData(dataArray) {
for (let data of dataArray) {
// 跳过无效数据
if (!isValid(data)) {
continue;
}
// 处理数据
let result = process(data);
// 如果处理失败,停止处理
if (!result.success) {
console.log("处理失败,停止处理");
break;
}
// 保存结果
saveResult(result);
}
}实际应用示例
数组处理工具函数
javascript
// 数组过滤函数
function filterArray(array, condition) {
const result = [];
for (let item of array) {
if (condition(item)) {
result.push(item);
}
}
return result;
}
// 数组映射函数
function mapArray(array, transform) {
const result = [];
for (let i = 0; i < array.length; i++) {
result.push(transform(array[i], i));
}
return result;
}
// 数组归约函数
function reduceArray(array, reducer, initialValue) {
let accumulator = initialValue;
for (let item of array) {
accumulator = reducer(accumulator, item);
}
return accumulator;
}
// 使用示例
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const evenNumbers = filterArray(numbers, n => n % 2 === 0);
console.log("偶数:", evenNumbers); // [2, 4, 6, 8, 10]
const squares = mapArray(numbers, n => n * n);
console.log("平方:", squares); // [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
const sum = reduceArray(numbers, (acc, n) => acc + n, 0);
console.log("总和:", sum); // 55对象属性处理
javascript
// 对象属性转换
function transformObject(obj, transformer) {
const result = {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
const transformed = transformer(key, obj[key]);
result[transformed.key] = transformed.value;
}
}
return result;
}
// 对象属性过滤
function filterObject(obj, predicate) {
const result = {};
for (let key in obj) {
if (obj.hasOwnProperty(key) && predicate(key, obj[key])) {
result[key] = obj[key];
}
}
return result;
}
// 使用示例
const user = {
name: "张三",
age: 25,
email: "zhangsan@example.com",
password: "secret123"
};
// 过滤敏感信息
const publicInfo = filterObject(user, (key, value) => key !== "password");
console.log(publicInfo); // { name: "张三", age: 25, email: "zhangsan@example.com" }
// 转换属性名
const transformedUser = transformObject(user, (key, value) => ({
key: key.toUpperCase(),
value: typeof value === "string" ? value.toUpperCase() : value
}));
console.log(transformedUser);
// { NAME: "张三", AGE: 25, EMAIL: "ZHANGSAN@EXAMPLE.COM", PASSWORD: "SECRET123" }循环性能测试
javascript
// 性能测试函数
function performanceTest(testName, testFunction, iterations = 1000000) {
const startTime = performance.now();
for (let i = 0; i < iterations; i++) {
testFunction();
}
const endTime = performance.now();
console.log(testName + " 耗时:" + (endTime - startTime) + " 毫秒");
}
// 测试不同循环的性能
const testArray = new Array(10000).fill(0).map((_, i) => i);
// for 循环
performanceTest("for 循环", () => {
let sum = 0;
for (let i = 0; i < testArray.length; i++) {
sum += testArray[i];
}
});
// for...of 循环
performanceTest("for...of 循环", () => {
let sum = 0;
for (let value of testArray) {
sum += value;
}
});
// forEach 循环
performanceTest("forEach 循环", () => {
let sum = 0;
testArray.forEach(value => {
sum += value;
});
});总结
JavaScript 循环语句的核心要点:
- for 循环:适用于已知循环次数的情况
- while 循环:适用于循环次数未知的情况
- do...while 循环:至少执行一次的循环
- for...in 循环:遍历对象属性
- for...of 循环:遍历可迭代对象
- 循环控制:break(退出循环)、continue(跳过本次循环)
- 标签语句:控制嵌套循环
- 性能优化:缓存长度、选择合适的循环类型
- 最佳实践:避免无限循环、合理使用控制语句
掌握循环语句是编写高效 JavaScript 程序的基础。在下一章节中,我们将学习 JavaScript 的函数。