javascript递归调用function向scope外数组push新值的时候为什么会同时改变整个数组的值?
高洛峰
高洛峰 2017-04-11 12:02:58
[JavaScript讨论组]

我本来想用javascript写一段程序,把兼并在一起的一行数据扩展成多行数据。比如下面这一行

[["a1","a2","a3","a4","a5","a6","a7"],["b1","b2","b3","b4","b5"],["c1","c2","c3"]]

我希望输出成

[ [ 'a1', 'b1', 'c1' ],
  [ 'a1', 'b1', 'c2' ],
  [ 'a1', 'b1', 'c3' ],
  [ 'a1', 'b2', 'c1' ],
  ...
  [ 'a7', 'b5', 'c1' ],
  [ 'a7', 'b5', 'c2' ],
  [ 'a7', 'b5', 'c3' ] ]

大致写了一下程序:

function tableDecompress(t){
  // var t = [["a1","a2","a3","a4","a5","a6","a7"],["b1","b2","b3","b4","b5"],["c1","c2","c3"]]
  var xecimal = t.map(function(e,i,a){
    if(ie.length).reduce((a,b)=>a*b)
  }
  var ttlCell = xecimalCalc(t)
  var result= new Array(ttlCell)
  result.fill([])
  fillIt(t,0,[],[])
  function fillIt(arrOutter,iOutter,valueStore,addr){
    arrOutter[iOutter].forEach(function(e,i,a){
      var vStore = valueStore
      var addrS = addr
      vStore[iOutter]=e
      addrS[iOutter]=i
      if(iOuttere*xecimal[i]).reduce((a,b)=>a+b)
        result[addrSeq]=result[addrSeq].concat(vStore)
      }
    })
  }
  return result
}

这里面:

function xecimalCalc(arr){
    return arr.map(e=>e.length).reduce((a,b)=>a*b)
  }
  var ttlCell = xecimalCalc(t)
  var result= new Array(ttlCell)
  result.fill([])

是我后面改过来的,原先就只是声明一个var result=[],在fillIt这个函数里面else分支直接result.push(vStore),但是如果这样做的话呢,就会变成下面的结果:

 [ 'a7', 'b5', 'c3' ],
 [ 'a7', 'b5', 'c3' ] ,
 [ 'a7', 'b5', 'c3' ] ,
 [ 'a7', 'b5', 'c3' ] 
....
 [ 'a7', 'b5', 'c3' ] ]

在else分支里面我试过console.log(vStore),还把addrS也算出来了,觉得这样子总不会重复覆盖了吧,但是仍旧不是那么回事。只有当我事先建好一个刚好够长的数组,把这个数组用[]填充好,之后不用赋值而是用concat的时候才能正常运行。

实在是搞不懂到底为啥会这样?

高洛峰
高洛峰

拥有18年软件开发和IT教学经验。曾任多家上市公司技术总监、架构师、项目经理、高级软件工程师等职务。 网络人气名人讲师,...

全部回复(1)
迷茫

多谢评论里的指点。所以问题是出在这两行代码:

var vStore = valueStore
var addrS = addr

对object用赋值只能是传递一个reference,要想做clone需要用下面的方法:

var vStore = valueStore.slice(0)
var addrS = addr.slice(0)

修改以后可以正常运行。

function tableDecompress(t){
  var result = []
  fillIt(t,0,[],[])
  function fillIt(arrOutter,iOutter,valueStore,addr){
    arrOutter[iOutter].forEach(function(e,i,a){
      var vStore = valueStore.slice(0)
      var addrS = addr.slice(0)
      vStore[iOutter]=e
      addrS[iOutter]=i
      if(iOutter<arrOutter.length-1){
        fillIt(arrOutter,iOutter+1,vStore,addrS)
      }else{
        result.push(vStore)
      }
    })
  }
  return result
}
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号