【问题标题】:Array elements not mutating inside for of loop数组元素在 for of 循环内不发生变异
【发布时间】:2020-10-13 17:48:24
【问题描述】:

function rot13(str) {
  let alphArr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
  let n = 13;
  let arr = str.split("");
  let len = alphArr.length;

  for (let i of arr) {
    if (alphArr.includes(i)) {
      if (alphArr.indexOf(i) + n <= len - 1) {
        i = (alphArr[alphArr.indexOf(i) + n])
        console.log(i) // This is as expected
      }
    }
  }

  console.log(arr) // Array itself did not mutate and is showing the initial array. 
  return str;
}

rot13("SERR PBQR PNZC");

第二个if 语句中i 的值是正确的,如console.log 语句中所示,但数组本身没有发生变异。为什么会这样?

附:我已经通过使用map 函数解决了它,它可以正常工作,因为map 函数不会改变原始数组。

【问题讨论】:

  • 你想做什么,预期的结果是什么?
  • 试试 console.log alphArr[alphArr.indexOf(i)+n]
  • 分配给i 不会更改数组。在这种情况下,您只是重新分配了一个不相关的变量。
  • 是当前数组项的。但是,更改它不会更改数组,因为JavaScript is not pass-by-reference
  • @VLAZ 现在我明白了。它由于按值传递,因为它只是表示元素的值。非常感谢您的澄清!

标签: javascript arrays string for-loop


【解决方案1】:

值得一提的是,你的代码可以简化:

let rot = (str, n, asciiStart='A'.charCodeAt(0), asciiEnd='Z'.charCodeAt(0), asciiRange=asciiEnd-asciiStart+1) =>
  str.split('')
    .map(c => {
      let code = c.charCodeAt(0) - asciiStart;
      if (code >= 0 && code <= asciiRange) code = (code + n) % asciiRange;
      return String.fromCharCode(asciiStart + code);
    })
    .join('');

let inp = document.getElementsByTagName('input')[0];
let p = document.getElementsByTagName('p')[0];

inp.addEventListener('input', () => p.innerHTML = rot(inp.value, 13));
<input type="text" placeholder="test here (use capital letters)"/>
<p></p>

您的代码不起作用,因为替换 i 的值不会影响 i 最初基于的数组索引。一旦你定义了i,它就不会记得它是如何定义的(例如,它不会自己思考,“我来自数组中的一个值”)

【讨论】:

    【解决方案2】:

    您不能直接在 for of 循环中为元素设置值,请尝试以下操作...

    function rot13(str) {
      let alphArr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
    
      let n = 13;
      let arr = str.split("");
      let len = alphArr.length;
    
      let j=0
      for (let i of arr) {
        if (alphArr.includes(i)) {
          if (alphArr.indexOf(i) + n <= len - 1) {
    
            arr[j]= (alphArr[alphArr.indexOf(i) + n])
            console.log(i) // This is as expected
    
          }
        }
        j++
      }
      console.log(arr) // Array itself did not mutate and is showing the initial array. 
    
    
      return str;
    }
    
    rot13("SERR PBQR PNZC");

    【讨论】:

    • 如果你要使用循环计数器,你也可以使用常规循环for (let i = 0; i &lt; arr.length; i++),并在里面使用arr[i]。将for..of 和计数器混合在一起很麻烦。更好的解决方案是只遍历数组中的条目,其中包括索引:for (let [index, element] of arr.entries())
    • 是的,我会为我的代码这样做,但在这里我使用了提问者提供的代码。
    • 抱歉解决方案混乱
    • 我不知道你不能做,我也没有找到任何文件说不能做。如果你发现了什么,请分享。
    • for of 循环中的元素仅包含您可以在 MDN 文档中看到的特定属性的值。
    【解决方案3】:

    您应该使用map 创建一个新数组并使用新映射的数组,而不是使用for of 循环。固定填充工作示例:

    function rot13(str) {
      let alphArr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
    
      let n = 13;
      let arr = str.split("");
      let len = alphArr.length;
    
      arr = arr.map((i) => {
        if (alphArr.includes(i)) {
          let index = (alphArr.indexOf(i) + n) % len;
            return alphArr[index];
          }
         return i;
      });
    
      return arr.join("");
    }
    
    console.log(rot13("SERR PBQR PNZC")); // logs "FREE CODE CAMP"

    【讨论】:

    • 我确实用 map 解决了这个问题,因为它不会像 Matt 指出的那样改变原始数组,但我只是对为什么在这种情况下原始数组没有发生变异感到困惑。
    • 感谢 VLAZ,我得到了答案。这是因为按值传递,这就是为什么 alphArr[alphArr.indexOf(i)+n] 会起作用的原因。
    猜你喜欢
    • 1970-01-01
    • 2016-03-24
    • 1970-01-01
    • 2019-12-06
    • 2019-09-16
    • 2018-08-14
    • 2020-07-10
    • 1970-01-01
    相关资源
    最近更新 更多