分支与循环:用 FizzBuzz 一次串起来

[迷你控制台]

一、for + if/else if:顺序不同,结果完全不同

for (let i = 1; i <= n; i++) {
  if (i % 15 === 0)      'FizzBuzz'   // 必须最先判断:15 的倍数同时是 3 和 5 的倍数
  else if (i % 3 === 0)  'Fizz'
  else if (i % 5 === 0)  'Buzz'
  else                   i 本身
}

把这些 if 写成平级(各自独立、不用 else)也不会「双重上色」,但用 else if 才能保证只命中第一个成立的分支——判断条件互斥时优先用 else if 或 switch。

二、for...of 取值,for...in 取「键」——数组上是字符串下标

const fruits = ['苹果', '香蕉', '橙子']
const user = { name: '阿蓝', age: 28 }

for (const v of fruits) { ... }   // v 是值:'苹果' '香蕉' '橙子'
for (const i in fruits) { ... }   // i 是下标,而且是字符串 '0' '1' '2'
for (const k in user)   { ... }   // k 是键名:'name' 'age'(遍历对象只能用 in)

规则记一条就够:数组和「可迭代对象」用 for...of,普通对象用 for...in(或 Object.entries())。对数组用 for...in 不仅拿到字符串下标,还会把挂在原型上的可枚举属性一起翻出来,是教科书级的错误写法。

三、while 先判断,do...while 先执行一遍

// while:条件为假时,循环体一次都不执行
let n = 1234
const digits = []
while (n > 0) { digits.push(n % 10); n = Math.floor(n / 10) }   // [4,3,2,1]

// do...while:至少执行一次,再判断要不要继续
let m = 0
do { log('执行了'); m++ } while (m > 0)

用途区分:while 适合「先把数字拆完 / 先把任务取完」这类可能为空的场景;do...while 适合「先做一次、再问要不要重复」的场景,比如菜单至少显示一次、重试至少发起一次。

四、break 提前收工,continue 跳过本轮

for (let i = 1; i <= 60; i++) {
  if (i % 3 === 0 && i % 5 === 1) { log('找到了:' + i); break }   // 找到就跳出整个循环
}

for (let i = 1; i <= 20; i++) {
  if (i % 2 !== 0) continue   // 奇数跳过本轮,直接进入 i++
  log(i)
}

五、switch:穿透(fallthrough)是特性,忘写 break 是 bug

星期:
switch (day) {
  case 6:
  case 7:
    return '周末'        // 有意穿透:6 与 7 共用同一段逻辑
  case 5:
    return '周五,马上放假'
  default:
    return '工作日'
}

// 没有 break 时不会退出,会继续往下执行所有 case:
// case 5: log('周五'); case 6: log('周六'); ... 一直穿透到结尾

规范写法:每个 case 结尾都写 break(或直接 return,在函数里更干净);只有「多个值共用一段逻辑」时才故意让 case 连续排列——比如 6 和 7 都落到「周末」。漏掉 default 则所有值都不匹配时什么也不做。switch 用的是严格相等 === 比较,字符串 '5' 不会命中数字 5。