array.push似乎替换了先前的对象,而不是附加

时间:2018-12-27 21:35:37

标签: javascript arrays html5-canvas

我想收集在画布上绘制的矩形的坐标。当我将下一组坐标插入到数组中时,数组中的每个先前条目将成为新的一组,而不是保留为它们的原始坐标。

我是一个为期一周的javascript老手,所以我很确定这是一个新手问题。我正在替换为演示给学生演示代数概念而编写的一个小型Excel VBA,因为并非每个学生的计算机上都具有Excel,并且Excel的在线版本不运行VBA宏。我想要一个可以下载并脱机运行的独立应用程序。 我画矩形没有问题。我希望arr(ndx)包含第ndx个矩形的坐标。最终,如果学生选择了一组矩形,我将更改该矩形的背景色。 我的控制台输出显示,在第ndx次迭代中,从0到ndx的所有arr条目都包含同一组坐标,即最后一个被捕获的坐标。 在我看来,arr.push正在用当前条目覆盖每个先前的条目,而不是将它们附加到数组中。我想念什么? 我删除了代码只是为了说明我遇到的问题。输出块最后一部分的随附console.log代码。

var arr = [];  var ndx = 0;   //array to contain rectangle coords  

Rows = 2; Cols = 3;           //Actual 40 X 60 or so.  
for (j=0; j<Rows;j++) {  
    for (i=0; i<Cols; i++) {  
        obj.row = j; obj.col = i;
        obj.xpos = obj.xpos + obj.xpos * j;     
        obj.ypos = obj.ypos + obj.ypos * i;  

        // will actually use fillRect() here to draw  
        //grid of rectangles spread across screen.  This works.  

        arr.push({obj});    // capture rect's coords for later reference  

        watchit0 = Object.entries(arr[ndx].obj);    //for debugging  
        if (ndx > 0) {  
            watchit1 = Object.entries(arr[ndx - 1].obj); }  
        else {  
            watchit1 = "                          ";  
        }  

        watchit2 = Object.keys(arr);    
        console.log("obj: " + Object.entries(obj)  
+ "     arr: " + watchit0 + "    arr-1: "  
+ watchit1 + "    keys: " + watchit2);

        ndx++;  
    }  
}  

//everything below is for debugging  
console.log("  ");  

watchit00 = Object.entries(arr[0].obj);  
watchit01 = Object.entries(arr[1].obj);  
watchit02 = Object.entries(arr[2].obj);  
watchit03 = Object.entries(arr[3].obj);  
watchit04 = Object.entries(arr[4].obj);  
watchit05 = Object.entries(arr[5].obj);  

console.log("     0: " + watchit00 + "     1:  " + watchit01);  
console.log("     2: " + watchit02 + "     3:  " + watchit03);  
console.log("     4: " + watchit04 + "     5:  " + watchit05);

console.log输出(重新格式化):

obj: row,0,col,0,xpos,1,ypos,10       
arr: row,0,col,0,xpos,1,ypos,10       arr-1:                                                       keys: 0

obj: row,0,col,1,xpos,1,ypos,20       
arr: row,0,col,1,xpos,1,ypos,20       arr-1: row,0,col,1,xpos,1,ypos,20       keys: 0,1

obj: row,0,col,2,xpos,1,ypos,60       
arr: row,0,col,2,xpos,1,ypos,60       arr-1: row,0,col,2,xpos,1,ypos,60       keys: 0,1,2

obj: row,1,col,0,xpos,2,ypos,60       
arr: row,1,col,0,xpos,2,ypos,60       arr-1: row,1,col,0,xpos,2,ypos,60       keys: 0,1,2,3

obj: row,1,col,1,xpos,4,ypos,120     
arr: row,1,col,1,xpos,4,ypos,120     arr-1: row,1,col,1,xpos,4,ypos,120    keys: 0,1,2,3,4

obj: row,1,col,2,xpos,8,ypos,360     
arr: row,1,col,2,xpos,8,ypos,360     arr-1: row,1,col,2,xpos,8,ypos,360    keys: 0,1,2,3,4,5

下面是在我的代码末尾输出arr[ndx]。 我期望6个条目与上面的obj:相匹配,但是每个条目都是最后一次迭代。为什么??

0:  row,1,col,2,xpos,8,ypos,360     
1:  row,1,col,2,xpos,8,ypos,360     
2:  row,1,col,2,xpos,8,ypos,360     
3:  row,1,col,2,xpos,8,ypos,360   
4:  row,1,col,2,xpos,8,ypos,360     
5:  row,1,col,2,xpos,8,ypos,360

2 个答案:

答案 0 :(得分:1)

史蒂夫。 第一个代码显示了错误原因的简化版本。 注意:如果要进行测试,则数组中的每个对象都是同一对象。

代码的第二张照片显示了在对象函数上使用Object.create获取新实例。

希望这会有所帮助。

let sampleArrValues = [1,2,3,4,5];

function myObject(num) {
  this.number = num;
}
console.log('Bad Array Demo');
// This wont work
let badArray = [];
var obj = new myObject(1);

sampleArrValues.forEach(num => {
  obj.number = num;
  badArray.push(obj);
});

// Lets look at the array content
badArray.forEach(item => {
  console.log(item.number);
});
// -> 5,5,5,5,5


console.log('Good Array Demo');
// Now do properly
var goodArray = [];

sampleArrValues.forEach(num => {
  obj = Object.create(myObject);
  obj.number = num;
  goodArray.push(obj);
});

goodArray.forEach(item => {
  console.log(item.number);
});
// -> 1,2,3,4,5

答案 1 :(得分:0)

这是您已经获得答案的另一种尝试:

  • 代码段的第一部分显示了您拥有的内容,但通常您不想要:单个对象存储在obj1变量的开头,并且将push放入{{将arr1设置为其他值后再返回1}}。控制台中的日志行显示x本身发生正确(数组增长),但是随着同一对象被多次存储,越来越多的内容都显示了通过push设置的最后一个值
  • 该片段的第二部分显示了您应该执行的操作:非常相似,但是在每次迭代中都使用一个全新的对象初始化obj1.x,因此不仅数组中的元素数量增加了,而且他们还引用了具有不同内容的不同对象。

obj2

旁注:在原始代码中,使用var obj1={x:1, toString:function(){return this.x;}}; var arr1=[]; for(var i=0;i<5;i++){ obj1.x=i; arr1.push(obj1); console.log(arr1.join()); } console.log("---"); var arr2=[]; for(var i=0;i<5;i++){ var obj2={x:i, toString:function(){return this.x;}}; arr2.push(obj2); console.log(arr2.join()); }并创建一个新对象(它是arr.push({obj});的简写),即新创建对象的arr.push({obj:obj});字段始终指的是您存储在obj开头的同一对象。