Skip to content

JavaScript 循环语句

循环语句是编程语言中的重要控制结构,用于重复执行一段代码直到满足特定条件。在 JavaScript 中,循环语句可以帮助我们高效地处理数组、对象和其他数据集合。掌握循环语句对于编写高效的 JavaScript 程序至关重要。在本章节中,我们将深入学习 JavaScript 中的各种循环语句。

循环语句的基本概念

循环语句允许我们重复执行代码块,避免重复编写相同的代码。JavaScript 提供了多种循环语句:

  1. for 循环
  2. while 循环
  3. do...while 循环
  4. for...in 循环
  5. 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); // 55

for 循环的组成部分

  1. 初始化:循环开始前执行一次
  2. 条件:每次循环前检查,为 true 时继续循环
  3. 更新:每次循环后执行

倒序循环

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 循环语句的核心要点:

  1. for 循环:适用于已知循环次数的情况
  2. while 循环:适用于循环次数未知的情况
  3. do...while 循环:至少执行一次的循环
  4. for...in 循环:遍历对象属性
  5. for...of 循环:遍历可迭代对象
  6. 循环控制:break(退出循环)、continue(跳过本次循环)
  7. 标签语句:控制嵌套循环
  8. 性能优化:缓存长度、选择合适的循环类型
  9. 最佳实践:避免无限循环、合理使用控制语句

掌握循环语句是编写高效 JavaScript 程序的基础。在下一章节中,我们将学习 JavaScript 的函数。

本站内容仅供学习和研究使用。