【问题标题】:Typescript:Splice an Object affects the copy object too打字稿:拼接对象也会影响复制对象
【发布时间】:2018-07-24 22:25:57
【问题描述】:

我正在尝试从数组中删除一个对象。所以我使用了splice,但在拼接之前我复制了一个对象

this.program.lstProgramdetails.forEach((lph: any) => {
            this.rtGridUp = Object.assign({}, lph);
            this.rtGridMid = Object.assign({}, lph);
            this.rtGridDown = Object.assign({}, lph);
            lph.Details.forEach((inm: any, index: number) => {              
                if (inm.Track !== null && inm.Track.TrackDateIn !== null) {
                    this.rtGridMid.Details.splice(index, 1);
                    this.rtGridDown.Details.splice(index, 1);
                } else if (inm.Track === null) {
                    this.rtGridUp.Details.splice(index, 1);
                    this.rtGridDown.Details.splice(index, 1);
                } else {
                    this.rtGridUp.Details.splice(index, 1);
                    this.rtGridMid.Details.splice(index, 1);
                }
            });
                    });

根据条件,两个数组应该被切片,一个应该得到对象而不拼接。

但是在控制台中观看它会清除所有 3 个数组。 有没有什么方法可以在不影响复制对象的情况下拼接该对象?

【问题讨论】:

  • 您正在创建浅拷贝。您要么必须使用递归进行深拷贝,要么如果您只需要 Details 数组的副本,您可以使用数组解构来制作它的浅拷贝,例如const copy = [...lph.Details]
  • 实现您想要的另一种方法是使用像slice 这样的纯函数,而不是创建对象的“第一级”副本,因为嵌套对象仍然是引用。
  • 能否详细说明。

标签: javascript typescript angular5


【解决方案1】:

说明

这里的问题是 Object.assign({}, objectToClone) 确实创建了您要克隆的对象的副本,但保留了嵌套对象的引用

const objectToClone = { a: 'a', b: { b: 'b' } };
const clone = Object.assign({}, objectToClone);

clone.b.b = 'c';
console.log(objectToClone, clone);

如您所见,该对象没有被深度克隆。

有关详细信息,请参阅Is this a good way to clone an object in ES6? 问题。

纯函数

纯函数是在不改变现有值的情况下计算新值的函数More details about pure and impure functions

所以,为了避免像您在这里遇到的副作用。实现此目的的一种巧妙方法是使用像 slice 这样的纯函数,它返回一个新值,而 splice 改变它及其可能的引用。

解决问题的方法

this.program.lstProgramdetails.forEach((lph: any) => {
  lph.Details.forEach((inm: any, index: number) => {
    const keys = [null, null];
    if (inm.Track !== null && inm.Track.TrackDateIn !== null) {
      keys = ['rtGridMid', 'rtGridDown'];
    } else if (inm.Track === null) {
      keys = ['rtGridUp', 'rtGridDown'];
    } else {
      keys = ['rtGridUp', 'rtGridMid'];
    }

    // ES7 syntax
    this[keys[0]].Details = [
      ...lph.Details.slice(0, index),
      ...lph.Details.slice(0, index + 1)
    ];
    this[keys[1]].Details = [
      ...lph.Details.slice(0, index),
      ...lph.Details.slice(0, index + 1)
    ];

    // Or if you prefer
    this[keys[0]].Details = lph.Details.slice(0, index).concat(
      lph.Details.slice(0, index + 1)
    );
    this[keys[1]].Details = lph.Details.slice(0, index).concat(
      lph.Details.slice(0, index + 1)
    );
  });
});

This is a cool video explaining it 也展示了 ES6 语法

我没有测试这段代码 sn-p 只是为了解释目的而写的。

希望这个答案对您有所帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-30
    • 2021-07-24
    • 2023-03-07
    • 2018-05-26
    相关资源
    最近更新 更多