Javascript 这个函数是如何变异非返回数组的

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

我想问一个更好的问题,但我不知道怎么问。谢谢你的帮助

***问题:我将数组变量发送到一个函数,它返回时发生了更改,尽管我没有返回它,甚至没有使用相同的变量名。所需函数:变量变量变量没有更改

我已经记录了该函数,并隔离了对下面[].forEach()语句的更改,并用***注释。我发送变量,但返回变量并分配给新的变量和。这是如何改变变量的

//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]);