阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > 循环语句规范

循环语句规范

作者:陈川 阅读数:32086人阅读 分类: JavaScript

循环语句是JavaScript中控制流程的重要工具,合理的规范能提升代码可读性和维护性。以下是常见的循环语句规范及实践建议。

基本循环类型的选择

优先使用for循环处理已知迭代次数的场景,while循环适合条件不确定的情况,for...of用于可迭代对象遍历。避免使用for...in遍历数组,除非需要处理稀疏数组的特殊情况。

// 推荐 - 数组遍历
const arr = [1, 2, 3];
for (let i = 0; i < arr.length; i++) {
  console.log(arr[i]);
}

// 推荐 - 可迭代对象
const set = new Set([1, 2, 3]);
for (const item of set) {
  console.log(item);
}

循环控制变量

循环计数器应使用let声明,避免污染外部作用域。计数器命名应具有描述性,单字母变量仅限简单循环。

// 不推荐
for (var i = 0; i < 10; i++) { /*...*/ }

// 推荐
for (let index = 0; index < users.length; index++) {
  const user = users[index];
  // ...
}

循环体复杂度控制

单个循环体内代码不应超过20行,复杂逻辑应提取为独立函数。嵌套循环超过两层时应考虑重构。

// 不推荐
for (const item of list) {
  // 50行业务逻辑...
}

// 推荐
function processItem(item) {
  // 复杂逻辑封装
}

for (const item of list) {
  processItem(item);
}

提前终止与跳过

合理使用breakcontinue时需添加注释说明条件。return可用于终止整个包含循环的函数。

for (const user of users) {
  if (user.inactive) continue; // 跳过非活跃用户
  
  if (user.role === 'admin') {
    foundAdmin = user;
    break; // 找到第一个管理员即终止
  }
}

性能优化要点

缓存数组长度、避免循环内重复计算、减少DOM操作等性能关键点需特别注意。

// 优化前
for (let i = 0; i < document.getElementsByTagName('div').length; i++) {
  // 每次循环都重新计算长度
}

// 优化后
const divs = document.getElementsByTagName('div');
for (let i = 0, len = divs.length; i < len; i++) {
  // 缓存长度
}

异步循环处理

使用for...of配合await处理异步循环,避免forEach中的异步问题。

// 不推荐
items.forEach(async (item) => {
  await process(item); // 不会按预期等待
});

// 推荐
for (const item of items) {
  await process(item); // 顺序执行
}

不可变原则

在循环中修改正在遍历的数组可能导致意外行为,需要特殊处理时应先创建副本。

const numbers = [1, 2, 3, 4];

// 危险操作
for (let i = 0; i < numbers.length; i++) {
  if (numbers[i] % 2 === 0) {
    numbers.splice(i, 1); // 改变原数组
    i--; // 必须手动调整索引
  }
}

// 更安全的方式
const filtered = numbers.filter(n => n % 2 !== 0);

循环与函数式编程

现代JavaScript中,许多循环场景可用map/filter/reduce等函数式方法替代,但需注意性能差异。

// 传统循环
let sum = 0;
for (const num of numbers) {
  sum += num;
}

// 函数式方案
const sum = numbers.reduce((acc, num) => acc + num, 0);

错误处理模式

循环内部的错误处理应使用try-catch包裹具体操作,避免因单个失败中断整个循环。

for (const task of tasks) {
  try {
    await executeTask(task);
  } catch (error) {
    console.error(`Task ${task.id} failed:`, error);
    continue; // 继续后续任务
  }
}

循环变量作用域

使用let声明的循环变量具有块级作用域,var会导致变量提升和共享问题。

// 问题示例
var funcs = [];
for (var i = 0; i < 3; i++) {
  funcs.push(() => console.log(i)); // 全部输出3
}

// 正确方案
const funcs = [];
for (let i = 0; i < 3; i++) {
  funcs.push(() => console.log(i)); // 输出0,1,2
}

循环与生成器

复杂循环逻辑可封装为生成器函数,实现惰性求值和更清晰的控制流。

function* paginate(items, pageSize) {
  for (let i = 0; i < items.length; i += pageSize) {
    yield items.slice(i, i + pageSize);
  }
}

for (const page of paginate(allItems, 10)) {
  // 每次处理10个元素
}

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌