Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
避免变异JavaScript数组_Javascript_Arrays_Typescript - Fatal编程技术网

避免变异JavaScript数组

避免变异JavaScript数组,javascript,arrays,typescript,Javascript,Arrays,Typescript,下面是我的代码 let traces = { ref: null, min: null, max: null, avg: null }; let learning = { "Application": "b3", "t": [ { "d": 2, "BinaryType": "Current" }, { "d": 3, "BinaryTy

下面是我的代码

let traces = { ref: null, min: null, max: null, avg: null };
let learning = {
    "Application": "b3",
    "t": [
        {
            "d": 2,
            "BinaryType": "Current"
        },
        {
            "d": 3,
            "BinaryType": "Max"
        },
        {
            "d": 4,
            "BinaryType": "Avg"
        },
        {
            "d": 5,
            "BinaryType": "Min"
        }
    ]
};

let traceArr = Object.assign([],learning.t);

traceArr.forEach(trace => {

    if (trace.BinaryType == 'Current') {            
        traces.ref = Object.assign({}, learning);   
        traces.ref.t = [];
        traces.ref.t.push(trace);
        traces.ref.t[0].BinaryType = 'Refeyrence';            
    }

    if (trace.BinaryType == 'Min') {           
        traces.min = Object.assign({}, learning);
        traces.min.t = [];
        traces.min.t.push(trace);            
    }

    if (trace.BinaryType == 'Max') {            
        traces.max = Object.assign({}, learning);
        traces.max.t = []
        traces.max.t.push(trace);            
    }

    if (trace.BinaryType == 'Avg') {            
        traces.avg = Object.assign({}, learning);
        traces.avg.t = [];
        traces.avg.t.push(trace);            
    }          
});

console.log("Output",traces);
console.log("Traces- Should be non mutated",traceArr);
console.log("Original",learning.t)
我假设当我修改数组的内容时,原始(学习)对象的内容不会受到影响

两个问题:

  • 我假设traces.ref.t=[];应更改新创建对象中的引用。不是吗
  • console.log(“Original”,learning.t)输出如下: 表示内容已更改(textrefeerence,该内容已更改 在数组迭代期间修改)。为什么会这样?还有什么 我应该做些什么来避免它

    “原件” [ { d:2, BinaryType:“引用范围” }, { d:3, 二进制类型:“Max” }, { d:4, 二进制类型:“平均值” }, { d:5, 二进制类型:“Min” } ]


    • 我认为Object.assign()不会进行深度复制。我很确定它正在创建一个新数组,其元素指向原始数组。进行深度复制的最简单方法是将其转换为json并返回

      let traceArr = JSON.parse(JSON.stringify(learning.t));
      
      最大的缺点是,如果你复制的任何东西都有循环引用,那么它就不起作用

      编辑:

      为了说明发生了什么,学习对象从

      let learning = {
          "Application": "b3",
          "t": [Object1, Object2, ...]
      }
      
      然后这种情况发生了

      let traceArr = Object.assign([], learning.t);
      
      它创建一个新数组并将learning.t的内容复制到其中。此时,Tracearl看起来像

      traceArr = [Object1, Object2, ...]
      
      然后,它循环遍历Tracearl中的项目,这些项目与learning.t中的相同对象,只是从不同的数组中指向

      if (trace.BinaryType == 'Current') {            
          // At this point, trace === Object1
      
          // Shallow copy of learning
          traces.ref = Object.assign({}, learning);
          // traces.ref = { "Application": "b3", "t": [Object1, Object2, ...] }
      
          // Create a new array for traces.ref.t
          traces.ref.t = [];
          // traces.ref = { "Application": "b3", "t": [] }
      
          // Adds Object1 (same object from learning.t) to the new array
          traces.ref.t.push(trace);
          // traces.ref = { "Application": "b3", "t": [Object1] }
      
          // Modify Object1
          traces.ref.t[0].BinaryType = 'Refeyrence';            
      }
      

      如果不希望traces.ret.t的元素指向与learning.t相同的对象,则需要创建新对象,即需要推送trace的副本而不是trace。或者,正如我所建议的,让Tracear成为learning.t的深度副本,这样所有的对象都是新的,没有任何东西是共享的。

      看起来你有两个问题,但都是关于一个共享对象的变异

      我假设traces.ref.t=[];应更改新创建对象中的引用。不是吗

      执行
      []
      将创建一个新的数组实例,但
      跟踪。ref
      仍在一开始就使用共享
      跟踪
      对象。您可能希望创建
      跟踪
      对象的副本。因为它没有任何嵌套值,所以在您的情况下,使用扩展语法是实现这一点的简单方法:


      const newTrace={…traces}
      
      console.log(“Original”,learning.t)输出如下图所示,表明内容已更改(在数组迭代期间修改的文本引用)。为什么会这样?我应该做些什么来避免它呢

      这是因为
      跟踪
      对象被推入数组,然后被修改。您还可以通过使用对象排列创建浅复制来解决此问题:

      newTrace.ref.t.push({…trace});
      
      仅通过这些更改,原始代码可能如下所示:

      let traces={ref:null,min:null,max:null,avg:null};
      让学习={
      应用程序:“b3”,
      t:[
      {
      d:2,
      二进制类型:“当前”
      },
      {
      d:3,
      二进制类型:“Max”
      },
      {
      d:4,
      二进制类型:“平均值”
      },
      {
      d:5,
      二进制类型:“Min”
      }
      ]
      };
      让tracerr=Object.assign([],learning.t);
      traceArr.forEach(trace=>{
      如果(trace.BinaryType==“当前”){
      
      const newTrace={…traces}; newTrace.ref=Object.assign({},learning); newTrace.ref.t=[]; newTrace.ref.t.push({…trace}); newTrace.ref.t[0].BinaryType=“Refeyrence”; } 如果(trace.BinaryType==“Min”){
      const newTrace={…traces}; newTrace.min=Object.assign({},学习); newTrace.min.t=[]; newTrace.min.t.push({…trace}); } 如果(trace.BinaryType==“Max”){
      const newTrace={…traces}; newTrace.max=Object.assign({},学习); newTrace.max.t=[]; newTrace.max.t.push({…trace}); } 如果(trace.BinaryType==“Avg”){
      const newTrace={…traces}; newTrace.avg=Object.assign({},学习); newTrace.avg.t=[]; newTrace.avg.t.push({…trace}); } }); 日志(“输出”,跟踪); log(“痕迹-应该是非变异的”,traceArr); console.log(“原件”,learning.t);

      。它包含一些类型错误,但这是避免突变的最小更改数。

      为什么我不能初始化空数组?这对我来说是最简单的选择,然后向其中添加元素?你可以这样做,但它会向元素添加引用,而不会复制。因为数组有对象,所以需要对对象进行深度复制。如果数组是基本的,比如字符串或整数,那么浅层拷贝就足够了。我更新了我的答案,希望能更好地说明发生了什么以及为什么需要进行学习的深层拷贝。t array.const newTrace={…traces}不会有帮助。我需要traces.min.t=[]语句来帮助我停止引用旧对象,并建议traces.min.t开始引用这个新数组。否则,如何更改javascript中的引用?记住我有一个traces.min=Object.assign({},learning);在我更改引用之前。所以我正在处理一个全新的对象(浅拷贝),我不清楚想要的结果是什么。您能提供您希望在问题中打印您的最后3个控制台日志吗?您还可以执行
      traces.ref={…learning,t:[]}
      。目前,您正在执行
      Object.assign({},学习)
      但是这是一个浅拷贝(与
      {…learning}
      相同),所以
      t
      仍然是相同的数组实例,但是执行
      {…learning,t:[]}
      将创建一个新的空数组实例