You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

除作用域外,JS循环内外声明变量的差异?附Mexican Wave案例

循环内外声明变量的差异:以Mexican Wave函数为例

问题背景

需要实现一个将字符串转换为“墨西哥波浪”的函数,示例效果:输入 "hello" 应返回 ['Hello', 'hEllo', 'heLlo', 'helLo', 'hellO']。

正确实现(splitStr声明在循环内)

function wave(str) {
  let waveArr = [];
  for (let i = 0; i < str.length; i++) {
    const splitStr = str.split(""); // 声明在循环内
    if (splitStr[i] !== " ") {
      splitStr[i] = splitStr[i].toUpperCase();
      waveArr.push(splitStr.join(""));
    }
  }
  console.log(waveArr);
  return waveArr;
}
wave("hello");
// 返回 ['Hello', 'hEllo', 'heLlo', 'helLo', 'hellO']

异常实现(splitStr声明在循环外)

将splitStr移到循环外后,返回结果变为 ['Hello', 'HEllo', 'HELlo', 'HELLo', 'HELLO'],每次迭代会保留之前已大写的字符,导致多个字符同时大写:

function wave(str) {
  let waveArr = [];
  const splitStr = str.split(""); // 声明在循环外
  for (let i = 0; i < str.length; i++) {
    if (splitStr[i] !== " ") {
      splitStr[i] = splitStr[i].toUpperCase();
      waveArr.push(splitStr.join(""));
    }
  }
  console.log(waveArr);
  return waveArr;
}
wave("hello");
// 返回 ['Hello', 'HEllo', 'HELlo', 'HELLo', 'HELLO']

问题解答

结果差异的原因

splitStr是数组,属于引用类型:

  • 循环内声明时,每次迭代都会调用str.split("")生成全新的数组副本,修改当前索引的字符后,这个副本会被加入结果数组,不会影响其他迭代的数组。
  • 循环外声明时,整个循环共用同一个数组引用。每次迭代修改索引i的字符为大写后,修改会永久保留在原数组中。下一次迭代时,数组里已有之前大写的字符,再修改新索引就会出现多个字符大写的情况。

除作用域外,循环内外声明变量的其他区别

  1. 引用类型的状态保留:数组、对象这类引用类型,循环外声明会复用同一个引用,每次修改都会改变其内部状态;循环内声明则每次创建新实例,状态互不干扰。
  2. 内存与性能:
    • 循环内声明值类型(字符串、数字等)时,现代JS引擎会做优化,性能差异极小;但创建复杂对象/数组时,频繁生成实例可能有微小性能开销。
    • 循环外声明可减少实例创建次数,但需注意引用类型的状态污染问题。
  3. 变量生命周期:循环内用const/let声明的变量,仅在当前迭代的块级作用域内有效,迭代结束后会被引擎回收;循环外声明的变量会在整个函数作用域内存在,直到函数执行完毕。

内容的提问来源于stack exchange,提问作者chickpea

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 16:58:57