JavaScript流程控制:if条件判断与for/while循环用法示例

作者:函数茶馆

时间:2026-11-03

浏览:650

深入讲解JavaScript流程控制核心语法,包含if条件分支与守卫语句、for循环生命周期、while与do...while循环机制及break/continue跳转用法,提供实用代码示例与专业图解。

文章目录
核心语法 适用环境:现代浏览器 / Node.js 阅读预计:10分钟
JavaScript 程序的默认执行方式是自上而下顺序解析执行。在实际业务中,系统需要根据用户状态作出分流响应,或者对批量数据重复执行处理,这就依赖流程控制语句。本文聚焦条件分支(if...else)与循环结构(for、while、do...while),通过具体的代码示例、执行步骤推导与选型依据,帮助读者掌握如何编写结构清晰、避免陷阱的流程控制逻辑。
JavaScript流程控制:if条件判断与for/while循环用法示例
图 1:JavaScript 流程控制三大基本范式(顺序执行、条件分支与循环迭代)

一、条件分支:if、else if 与 else 的判断机制

条件判断语句允许程序在不同条件下执行不同的代码路径。其核心依托于括号内的表达式求值结果——在 JavaScript 运行时中,该表达式会被隐式转换为布尔值(Boolean)。

1. 基础语法与多分支结构

当只需要在条件成立时做处理,使用单个 if;当存在二选一逻辑时,搭配 else;面对多个互斥区间时,则使用 else if 进行串联阶梯判断。

示例 1:用户会员折扣分级计算
function calculateDiscount(userLevel, cartAmount) {
  let finalAmount = cartAmount;

  if (userLevel === 'diamond') {
    // 钻石会员享受 7 折
    finalAmount = cartAmount * 0.7;
  } else if (userLevel === 'gold') {
    // 黄金会员享受 8.5 折
    finalAmount = cartAmount * 0.85;
  } else if (cartAmount >= 500) {
    // 普通用户满 500 减 50
    finalAmount = cartAmount - 50;
  } else {
    // 无优惠
    finalAmount = cartAmount;
  }

  return finalAmount;
}

// 示例调用输出
console.log(calculateDiscount('gold', 1000)); // 输出示例:850
console.log(calculateDiscount('normal', 600)); // 输出示例:550

2. 隐式类型转换与真假值(Truthy / Falsy)

在 if (condition) 中,JavaScript 并不强制要求 condition 必须是严格的布尔类型。如果传入非布尔值,引擎会自动调用内部抽象操作将其转为布尔值。了解 JavaScript 中的八个“假值(Falsy)”至关重要:

  • false(布尔假)
  • 0、-0、0n(数值零与 BigInt 零)
  • ""(空字符串)
  • null(空对象引用)
  • undefined(未定义)
  • NaN(非数值)

除上述假值外,所有其他值(包括空数组 []、空对象 {} 以及字符串 "0")均为真值(Truthy)。

⚠️ 逻辑陷阱提醒:数字 0 与空字符串的判空错误
若编写 if (count) 来判断数量是否传入,当 count = 0 时会被当成 false 误判为“未传入”。针对数值或配置项,应使用精准的比较运算符,例如:if (count !== undefined && count !== null)。

3. 进阶实践:用守卫语句(Guard Clause)消灭嵌套

在复杂业务逻辑中,多层嵌套的 if...else 会导致代码向右倾斜(被称为“回调地狱”或“箭头型代码”),极大增加了阅读和重构的难度。专业规范通常推荐使用守卫语句(提前返回)将异常边界在函数起始处剔除,保持核心主流程居左平铺。

JavaScript流程控制:if条件判断与for/while循环用法示例
图 2:if 分支推导演进:阶梯式级联与扁平守卫语句对比
示例 2:重构前后的守卫模式对比
// ❌ 反例:深度嵌套难以阅读
function processOrder(order) {
  if (order) {
    if (order.status === 'PAID') {
      if (order.items.length > 0) {
        return shipItems(order.items);
      } else {
        return '订单无商品';
      }
    } else {
      return '订单尚未付款';
    }
  } else {
    return '订单不存在';
  }
}

// ✅ 推荐:扁平化守卫语句,提前返回
function processOrderClean(order) {
  if (!order) return '订单不存在';
  if (order.status !== 'PAID') return '订单尚未付款';
  if (order.items.length === 0) return '订单无商品';

  // 主干流程完全无缩进负担
  return shipItems(order.items);
}

二、计数循环:for 循环的生命周期与执行步骤

当需要在进入循环前就能确定迭代次数,或者需要按特定步长访问数组索引时,标准 for 循环是最通用、执行效率最高的基础结构。

1. for 循环的四段式生命周期

标准 for 语句头部包含三个由分号分隔的表达式:for (初始化; 条件判断; 步进更新) { 循环体 }。它们在运行时的执行顺序严格遵循四步流水线:

  1. 初始化表达式(Initialization):在循环启动前执行一次,常用于使用 let 声明循环变量。
  2. 条件判断表达式(Condition):在每轮迭代开始前求值。若计算结果为 true,进入循环体;若为 false,彻底终止并退出循环。
  3. 循环体语句块(Statement Block):条件满足时执行的业务逻辑。
  4. 步进更新表达式(Final-expression):循环体执行完毕后执行,改变计数器状态,随后立即回到步骤 2 重新判断。
JavaScript流程控制:if条件判断与for/while循环用法示例
图 3:标准 for 循环四阶段生命周期与执行闭环

2. 典型实战用法与性能细节

示例 3:数组倒序遍历与长度缓存
const productList = ['键盘', '鼠标', '显示器', '显卡', '主板'];

// 技巧 A:正序遍历时缓存数组长度,避免在每轮循环重复读取 length 属性
for (let i = 0, len = productList.length; i < len; i++) {
  console.log(`位置 ${i + 1}:${productList[i]}`);
}

// 技巧 B:倒序遍历(适合在循环中需要安全执行 splice 删除元素的情景)
for (let i = productList.length - 1; i >= 0; i--) {
  if (productList[i] === '显卡') {
    console.log(`在索引 ${i} 处命中关键物料`);
  }
}
💡 作用域隔离细节:let 与 var 在循环中的本质区别
若在 for 中使用 var i = 0,由于 var 变量提升至函数或全局作用域,循环内若存在异步回调(如 setTimeout 或点击事件监听),所有回调访问的均是同一个最终状态的 i。而 let 具有块级作用域特性,JavaScript 引擎在每次迭代时都会为该轮循环创建独立的变量环境绑定,从而保证异步操作能准确捕获当前轮次的索引值。

三、状态驱动循环:while 与 do...while 循环

与按索引计数的 for 循环不同,while 和 do...while 循环通常用于事先无法预知具体需要执行多少轮、完全取决于某个动态状态演进或外部数据到来的场景。

1. while 循环:先验条件验证

while 循环在进入执行体之前必须先通过条件求值门禁。如果初始条件即为 false,循环体一次都不会运行。因此其最小执行次数为 0 次。

示例 4:二分查找(Binary Search)与条件递进
function binarySearch(sortedArr, target) {
  let left = 0;
  let right = sortedArr.length - 1;

  // 依赖双指针状态夹逼,未知具体循环次数
  while (left <= right) {
    const mid = Math.floor((left + right) / 2);
    const midVal = sortedArr[mid];

    if (midVal === target) {
      return mid; // 命中目标直接返回索引
    } else if (midVal < target) {
      left = mid + 1; // 调整左边界
    } else {
      right = mid - 1; // 调整右边界
    }
  }

  return -1; // 未检索到目标
}

const numbers = [12, 25, 33, 47, 59, 68, 81, 95];
console.log(binarySearch(numbers, 59)); // 输出示例:4
console.log(binarySearch(numbers, 100)); // 输出示例:-1

2. do...while 循环:后验条件保证

do...while 结构将判断语句放在循环体末尾。这意味着无论条件是否满足,循环体都无条件至少执行 1 次,随后再依据条件决定是否开启后续轮次。

示例 5:网络请求重试器
function fetchWithRetry(maxRetries) {
  let attempts = 0;
  let success = false;
  let result = null;

  do {
    attempts++;
    console.log(`开始第 ${attempts} 次请求尝试...`);

    // 模拟偶发性网络调用
    const isMockSuccess = attempts === 3;
    if (isMockSuccess) {
      success = true;
      result = '数据拉取成功';
    }
  } while (!success && attempts < maxRetries);

  return { success, attempts, result };
}

// 示例调用输出
console.log(fetchWithRetry(5));
// 示例输出结果:{ success: true, attempts: 3, result: '数据拉取成功' }
JavaScript流程控制:if条件判断与for/while循环用法示例
图 4:while 与 do...while 执行逻辑对比及控制流向

四、流程干预与跳转:break 与 continue

在循环执行过程中,若满足特定前提,我们经常需要提前打断循环周期或跳过部分逻辑。JavaScript 提供了 break 与 continue 两个关键字来实现精细控制。

1. break:终止并跳出整个循环

break 语句会立即中断当前所在的整个循环结构,并将程序控制权移交给循环语句闭合大括号之后的下一条语句。常用于“寻找首个匹配元素后即刻停机”,避免无效空转。

2. continue:跳过当前轮次剩余代码

continue 并不会终止整个循环,而是仅放弃执行当前这一轮迭代中位于其后的语句,直接跳往步进更新阶段(在 for 中)或条件测试阶段(在 while 中),继而启动下一轮循环。

示例 6:结合 break 与 continue 处理数据流
const rawPayloads = [
  { id: 101, valid: true, value: 50 },
  { id: 102, valid: false, value: 0 },   // 无效数据:需跳过
  { id: 103, valid: true, value: 120 },
  { id: 999, isEndSignal: true },        // 终止哨兵:需中断
  { id: 104, valid: true, value: 80 }
];

let totalValidScore = 0;

for (let i = 0; i < rawPayloads.length; i++) {
  const item = rawPayloads[i];

  // 遇到结束信号,立即彻底退出循环
  if (item.isEndSignal) {
    console.log(`在索引 ${i} 捕获到终止哨兵,停止处理。`);
    break;
  }

  // 过滤无效数据项,提前进入下一轮
  if (!item.valid) {
    continue;
  }

  totalValidScore += item.value;
}

console.log(`有效积分统计总和: ${totalValidScore}`); // 输出示例:170

五、流程控制方案选型决策与避坑指南

在面对具体开发场景时,选择最贴合语义与性能要求的控制结构,能够使代码更具可读性并降低维护成本。下表汇总了各种语法的适用边界与推荐用法:

控制结构 先决条件 / 特征 最小执行轮次 最佳业务场景
if...else if 多条件布尔范围测试 根据匹配决定 业务规则判定、权限校验、参数区间划分
for 循环 已知执行轮次、需要计数器 0 次 数组定长遍历、矩阵算法计算、多步步长递进
while 循环 未知循环次数、依赖外部信号 0 次 二分收敛、轮询外部状态、游标分页拉取
do...while 必须无条件优先尝试执行一次 1 次 命令行用户交互、网络重试器、密码输入验证
for...of 直接访问可迭代对象的值 0 次 现代日常开发中遍历 Array、Set、Map 数据
JavaScript流程控制:if条件判断与for/while循环用法示例
图 5:流程控制全场景选型决策树与高频避坑清单

常见易错陷阱与防护措施

  1. 死循环(Infinite Loop):编写 while 或 for 循环时,必须确保循环体内存在能够推进条件向 false 演进的语句。对于复杂的异步轮询,始终建议加入硬性最大重试上限(如 attempts < MAX_LIMIT)。
  2. 差一错误(Off-by-One Error):数组的合法索引范围为 0 至 arr.length - 1。正向遍历的标准边界判断应为 i < arr.length,误写为 i <= arr.length 会导致最后一轮访问越界返回 undefined。
  3. 在循环体中修改正在遍历的集合:在使用 for 遍历数组并同时执行 splice 删除元素时,会导致后续元素的索引前移,造成元素遗漏。建议采用倒序遍历、或者使用不可变数组方法(如 filter)生成新数组。
📌 总结
条件判断与循环构成了 JavaScript 程序的骨架。善用守卫语句避免复杂分支嵌套,在明确边界时选择 for 循环,在状态驱动时使用 while / do...while,并在适当的时机使用 break 与 continue 优化执行路径,是写出健壮、高效前端与服务端代码的基本功。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章