【问题标题】:.push() overwrites array values in Javascript.push() 覆盖 Javascript 中的数组值
【发布时间】:2020-07-15 17:43:31
【问题描述】:

我检查了“类似问题”,但我要么不理解答案,要么它们似乎与这个问题无关。

在某些情况下,当我尝试 (Loop3) 时,我似乎无法覆盖数组值,而在其他情况下,当我认为它们不应该被覆盖时,数组值会被覆盖 (Loop4)。我刚刚编辑了代码以在各个点显示更多值。

<script>
function manual() {
    myArray = [];
    td=[1,2,3];
    myArray.push(td);
    td=[4,5,6];
    myArray.push(td);
    alert(myArray[0]); // Properly reports [1,2,3]
}

function loop() {
    myArray = [];
    td = [];
    for (i=0; i<=1; i++) {
        if (i==0) td=[1,2,3];
        else if (i==1) td=[4,5,6];
        myArray.push(td);
    }
    alert(myArray[0]); // Properly reports [1,2,3]
}

function loop2() {
    myArray = [];
    td = [];
    for (i=0; i<=1; i++) {
        td[i] = 9;
    }
    td = [1,2,3]; // Attempt to overwrite existing values
    myArray.push(td);
    alert(myArray[0]); // Properly returns 1,2,3
}

function loop3() {
    myArray = [];
    td = [];
    for (i=0; i<=1; i++) {
        for (j=0; j<=2; j++) {
            td[j] = 9;
        }
        if (i==0) td=[1,2,3];
        else if (i==1) td=[4,5,6];
        myArray.push(td);
    }
    alert(myArray[0]); // Returns 9,9,9 when I expect 1,2,3
}

function loop4() {
    myArray = [];
    td = [];
    tb = document.getElementById('myTable');
    for (i=0; row = tb.rows[i]; i++) {
        for (j = 0; col = row.cells[j]; j++) {
            td[j] = col.innerHTML;
        }
        alert("td="+td); // Properly get 1,2,3 the 1st time, 4,5,6 the 2nd time
        myArray.push(td);
        alert(myArray); // Expect 1,2,3 the 1st run, and that's what I get
                   // Expect 1,2,3 | 4,5,6 the 2nd run, but get 4,5,6 | 4,5,6
    }
}

</script>

<table id=myTable>
<tr><td>1</td><td>2</td><td>3</td></tr>
<tr><td>4</td><td>5</td><td>6</td></tr>
</table>

<button onclick=manual()>Manual</button>
<button onclick=loop()>Loop</button>
<button onclick=loop2()>Loop2</button>
<button onclick=loop3()>Loop3</button>
<button onclick=loop4()>Loop4</button>

【问题讨论】:

    标签: javascript arrays push


    【解决方案1】:

    在函数 4 中,您覆盖了您的数组元素。因为在第二个你输入两次。第一个你的数组填充 1,2,3 然后第二个填充 4,5,6 最终结果是 4,5,6

    如果你想要 1,2,3,你可以检查你的数组是否为空

    function loop4() {
        myArray = [];
        td = [];
        tb = document.getElementById('myTable');
        for (i=0; row = tb.rows[i]; i++) {
            for (j = 0; col = row.cells[j]; j++) {
                td[j] = td[j] ? td[j] : col.innerHTML;
            }
            myArray.push(td);
        }
        console.log(myArray[0]); // Expect 1,2,3, actually get 4,5,6
    }
    <table id="myTable">
    <tr><td>1</td><td>2</td><td>3</td></tr>
    <tr><td>4</td><td>5</td><td>6</td></tr>
    </table>
    
    <button onclick="manual()">Manual</button>
    <button onclick="loop()">Loop</button>
    <button onclick="loop2()">Loop2</button>
    <button onclick="loop3()">Loop3</button>
    <button onclick="loop4()">Loop4</button>

    【讨论】:

    • 谢谢,但这对我来说毫无意义。我正在推送一个应该创建新行的数组,为什么第一行会被覆盖?我也不明白你的代码的目的,以及为什么它是必要的。最后,我仍然遇到我用 loop3 确定的问题。
    【解决方案2】:

    你应该初始化你的循环索引,像这样:for (var i=0; i&lt;=1; i++)

    【讨论】:

      【解决方案3】:

      这不是数组的内置方法push() 的问题,问题是您正在改变td 数组。我们以loop3 为例:

      • 在i=0 迭代结束时,td 然后是[1,2,3],而myArray 是[[1,2,3]] - 它存储绑定到td 的数组引用
      • 在i=1 迭代开始时,在j 循环之后(在该循环中,您改变了由td 绑定的前一个数组引用),td 然后是[9,9,9] 和@987654335 @(持有该数组引用)也会受到影响,导致 [[9,9,9]]

      function mutatedLoop3() {
        myArray = []
        td = []
        for (i = 0; i <= 1; i++) {
          console.log('previous td', JSON.stringify(td))
          for (j = 0; j <= 2; j++) {
            td[j] = 9
          }
          console.log('mutated td', JSON.stringify(td))
          if (i == 0) td = [1, 2, 3] // you reassign to a new array, means new reference
          else if (i == 1) td = [4, 5, 6]
          myArray.push(td)
          console.log(JSON.stringify(td), JSON.stringify(myArray))
          console.log('---')
        }
        console.log(myArray[0]) // Returns 9,9,9 when I expect 1,2,3
      }
      
      function fixedLoop3() {
        myArray = []
        for (i = 0; i <= 1; i++) {
          td = [] // now it is reset every iteration
          for (j = 0; j <= 2; j++) {
            td[j] = 9
          }
          if (i == 0) td = [1, 2, 3]
          else if (i == 1) td = [4, 5, 6]
          myArray.push(td)
          console.log(JSON.stringify(td), JSON.stringify(myArray))
          console.log('---')
        }
        console.log(myArray[0]) // Returns 9,9,9 when I expect 1,2,3
      }
      
      mutatedLoop3()
      fixedLoop3()

      【讨论】:

      • 谢谢你,但我不明白你的解释的任何部分。我看到移动 td = [] 是一个修复,但我不明白为什么。
      • 当你将一个数组分配给一个变量时,你实际上是在分配它的引用,即[1,2,3],当你将它推送到myArray时,你也会把它引用,比如@987654340 @。假设myArray[0] 和td 在i=1 迭代开始时持有数组[1,2,3] 的引用。因此,当您将td[j] 分配给 9 时,您也会更新myArray[0][j] 的值,这就是为什么在j 循环之后,td 和myArray[0] 都是[9,9,9]。将td=[] 移动到迭代的开头意味着您“摆脱”了对myArray[0] 的引用,因此它的值将不再受到影响
      【解决方案4】:

      我想通了。这是答案。

      // When you push an array or array element to another array,
      //  you don't copy the *data* to the new array;
      //  you copy a *reference* to the original array or array element.
      // If you change the elements of the original array,
      //  the elements you pushed also change.
      
      main = [];
      sub = [1,2,3];
      main.push(sub); // main now contains 1,2,3 as a *reference* to the sub
      sub[0]=9;
      alert(main); // Contains 9,2,3
      
      //------------------------------------------------------------------------------------
      // Redefining the original array destroys the link/reference.
      //------------------------------------------------------------------------------------
      main = [];
      sub = [1,2,3];
      main.push(sub); // main now contains 1,2,3 as a *reference* to sub
      sub = []; // sub has been redefined, destroying the link.  
      sub[0]=9;
      alert(main); // Contains 1,2,3
      
      //------------------------------------------------------------------------------------
      // Setting the values for a whole array redefines it, destroying the links.
      //------------------------------------------------------------------------------------
      main = []; // Redefines the array, destroying links
      main = [4,5,6]; // Providing initial values redefines the array, too
                      //  (destroying links).
      
      //------------------------------------------------------------------------------------
      // Changing the value of an element is *not* a redefinition of the array,
      //  so links persist.
      //------------------------------------------------------------------------------------
      main = [];
      sub = [1,2,3];
      main.push(sub); // main now contains 1,2,3 as a *reference* to sub
      sub[0]=9; // Does not redefine main, only changes one of its element.  Refs remain intact.
      alert(main); // Contains 9,2,3

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-10-02
        • 2022-01-23
        • 1970-01-01
        • 2010-12-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多