我对我的JavaScript代码中发生的事情感到非常困惑。我试图编写一个函数来创建一个随机点的数组。然而,当我在循环内记录数组(该循环的功能是向数组中添加点)时,然后在循环外再次记录它,我得到了两个不同的数组打印出来。
第一个,正如预期的那样,是随机X,Y点的列表,但第二个日志只包含最后输入的X,Y点。
function Pick(){ var numPoints = 4 * Math.floor(4+Math.random()*5); var chosen_pts = []; var lastPt; for(var i = 0;i<numPoints;i++) { if(chosen_pts.length==0) { var temp = new Point(Math.floor(Math.random()*250),Math.floor(Math.random()*250)); var newPt = pickClose(temp); chosen_pts.push(newPt); lastPt = newPt; } else{ var newPt = pickClose(lastPt); chosen_pts.push(newPt); } console.log(chosen_pts[i]); //LINE 106 } console.log("\noutside of the loop:") for(var i = 0;i<numPoints;i++) { console.log(chosen_pts[i]); //LINE 111 }}
编辑:
function pickClose(lastPt){ var x = lastPt["X"]; var y = lastPt["Y"]; var dx = 0; var dy = 0; var rand = Math.floor(1+Math.random()*100); if(rand<50){ dx = 1+Math.floor(Math.random()*10); dy = 1+Math.floor(Math.random()*10); if( (dx+dy)%3==0 ){ dx*=-1; } } else if(rand<80) { dx = 1+Math.floor(Math.random()*25); dy = 1+Math.floor(Math.random()*25); if( (dx+dy)%3==0 ){ dy*=-1; } } else{ dx = 1+Math.floor(Math.random()*60); dy = 1+Math.floor(Math.random()*60); if( (dx+dy)%4==0 ){ dx*=-1; dy*=-1; } } if( (x+dx) < 500&& (x+dx) >=0 ) lastPt["X"]+=dx; else lastPt["X"]-=dx; if( (y+dy) < 500&& (y+dy) >=0 ) lastPt["Y"]+=dy; else lastPt["Y"]-=dy; return lastPt; }
看起来相当混乱,但本质上我想根据初始随机数为(dx,dy)随机选择不同的值范围。
回答:
pickClose
函数总是返回传入的元素。JavaScript中的对象是通过引用传递的,因此你后来对对象所做的任何更改也将应用于你存储的所有其他对该对象的引用。
为了澄清:
var point1 = new Point(1, 2);var point2 = pickClose(point1);// 在pickClose内部,参数lastPt = point1: lastPt["X"] += dx; // <- 这也改变了point1! lastPt["Y"] += dy; // <- 这也改变了point1!
所以,如果你想在函数内部返回一个新的 Point
(而不改变传入的点),你必须创建一个新的对象来修改并返回:
var newX = x, newY = y;// 而不是:lastPt["X"]+=dx;// 做:newX += dx;// 然后,在底部,而不是return lastPt;// 创建一个新实例return new Point(newX, newY);