Javascript 这个函数是如何变异非返回数组的
我想问一个更好的问题,但我不知道怎么问。谢谢你的帮助 ***问题:我将数组变量发送到一个函数,它返回时发生了更改,尽管我没有返回它,甚至没有使用相同的变量名。所需函数:变量变量变量没有更改 我已经记录了该函数,并隔离了对下面[].forEach()语句的更改,并用***注释。我发送变量,但返回变量并分配给新的变量和。这是如何改变变量的Javascript 这个函数是如何变异非返回数组的,javascript,arrays,google-apps-script,Javascript,Arrays,Google Apps Script,我想问一个更好的问题,但我不知道怎么问。谢谢你的帮助 ***问题:我将数组变量发送到一个函数,它返回时发生了更改,尽管我没有返回它,甚至没有使用相同的变量名。所需函数:变量变量变量没有更改 我已经记录了该函数,并隔离了对下面[].forEach()语句的更改,并用***注释。我发送变量,但返回变量并分配给新的变量和。这是如何改变变量的 //this is what calls the sub function using vari, an array, 411.0, 13.0 var sum
//this is what calls the sub function using vari, an array, 411.0, 13.0
var sum = doSum1(vari);
function doSum1(vari0) {
// called from doSum1
// grab Variance data // ALL COLUMNS FOR NOW // fix loc/stat columns below
var vstat = vari0[0].indexOf('Status');
vari1 = vari0.filter(r=>r[vstat]); // to ensure indexOf works, and speed processing
var vhdr = ['Campaign ID','Campaign','Site ID','Site','Placement','Placement ID','Date','DCM Imp','Upw Imp','Tag Location','Status','Site Count','Site Imp'];
// move loc and status over in place of variance and percent (loc/stat will be site ct/imp)
varis=[];
// *** THIS FOREACH CHANGES varis AND vari. Not sure how... see more specifically below
['Not Tracking','Undertracking','Overtracking','Absent in DCM'].forEach(rf=>{
varis.push(vhdr.map(r=>''));
varis[varis.length-1][0]=rf;
varis.push(vhdr);
if(vari1.filter(r=>r[vstat].indexOf(rf)>=0).length==0) {
varis.push(vhdr.map(r=>''));
varis[varis.length-1][0]='none found';
} else {
varis.push(vari1.filter(r=>r[vstat].toString().indexOf(rf)>=0)[0]); // break out of outer []
//fix loc/stat location
//*** MORE SPECIFICALLY, this line in particular changes in vari, not just varis as intended.
varis[varis.length-1].splice(9,4,varis[varis.length-1][11],varis[varis.length-1][12],'','')
}
varis.push(vhdr.map(r=>'')); // trailing blank line
});
return varis;
我也试着用这个代替拼接,但结果一样。。。只是不知道varis是如何改变vari
varis[varis.length-1][9] = varis[varis.length-1][11];
varis[varis.length-1][10] = varis[varis.length-1][12];
varis[varis.length-1][11] = '';
varis[varis.length-1][12] = '';
vari
是一个二维数组。这意味着vari
中的每个元素也是一个数组,因此通过引用传递,并可能发生变异
该方法改变其参数数组。在代码中,每个varis[varis.length-1].splice()
调用修改通过引用从vari1
复制的数组对象,因此也修改vari0
,其元素是通过引用复制到vari1
的数组对象。这就是导致变异的原因
要避免此问题,请使用以下模式之一:
var vari1 = vari0.map(row => row.slice()).filter(r => r[vstat]);
或
模式使用和获取vari0
(即vari
)引用的2D数组的浅拷贝
第一个map()。行是数组,因此是可变的,因此需要一个slice()
或另一个map()
来将行复制到新数组中
请注意,复制是浅的,这意味着只有文本字符串和数字等基本值是按值复制的。您的注释表明vari
的行只包含原语,因此模式将生成一个可以安全修改且不会变异的副本vari
。如果vari
2D数组的行包含更多的数组或其他对象,则会通过引用复制,因此仍然会发生变异
请注意,和彼此非常不同。该方法改变其参数数组。该方法创建数组的浅层副本,实际上通常用于安全地复制包含基元的一维数组。在您的用例中,vari
数组不包含基元,而是包含数组,因此我们需要在map()
中调用slice()
,以复制2D数组第二级中的基元值
在一般情况下,深度克隆一个数组或另一个对象非常复杂。上面的模式可能是在您的用例中实现这一点的最简单方法。请参见对象(包括数组)是可变值。也就是说,任何引用它的东西都可以更改它。与其发送对象,不如发送一个副本。您能否显示函数llog()
。我看不到其他地方可以更改vari0
或vari0
,这些vari1
和varis
是全局变量吗?我会尝试在定义它们的行中添加var
。为了安全起见,谢谢大家。我应该有一个var定义。我要补充一点。我也可以寄一份。这是个好消息。有人知道这里具体是什么改变了vari吗?这个问题是在我添加log函数之前出现的。我应该注意,llog函数只是Logger.log。它没有任何作用。我把它放在那里是为了找出错误。我只是不喜欢输入'Logger.log'。如果它真的做了什么,它只会对[248]做点什么,对吗?无论如何,虽然我同意vari可能会发生变异,但我不知道这可能发生在何处。vari0[248]
是一个数组对象,可以在函数调用期间进行变异,但这不是问题的根源。编辑了答案。我想可能是这样的。我在几个地方试过const。我重新创建了您的具体建议(不确定为什么需要splice()。不过运气不好。这个错误仍然存在。我对const vs var不太熟悉。我读过,但看起来基本上是一样的。我可以为vari(不是vari)做const吗?如果不考虑,因为我正在更改值并返回它。。。这会有帮助吗?答案中的要点不是const
vs.var
,而是使用map map
或slice()
创建数组的副本。如果愿意,可以使用var
代替const
。编辑了答案。
var vari1 = vari0.map(row => row.map(value => value)).filter(r => r[vstat]);