.push() 覆盖 Javascript 中的数组值

.push() overwrites array values in Javascript

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

在某些情况下,我尝试时似乎无法覆盖数组值 (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>

在函数 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>

您应该初始化循环索引,如下所示:for (var i=0; i<=1; i++)

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

  • i=0 迭代结束时,td 然后是 [1,2,3],而 myArray[[1,2,3]] - 它存储绑定到 td
  • i=1 迭代开始时,在 j 循环之后(您在其中改变了先前的数组引用,它由 td 绑定),td 然后是 [9,9,9] 并且 myArray (保存该数组引用)也会受到影响,导致 [[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()

我明白了。答案在这里。

// 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