Array.push执行深拷贝而不是浅拷贝

时间:2016-05-29 02:24:15

标签: javascript typescript angular

上下文

我正在使用Typescript / Angular2 RC1作为我的webapp,我有两个类。在class1(Angular2服务)中,我有一个变量myVar = [obj1, obj2, obj3],在class2(Angular2组件)中,我使用myLocalVar = class1.myVar在构造函数中获取viewInjector来注入服务。

问题

在class2中,我使用myVar复制push(浅副本,因为它复制了对象),因此myLocalVar等于[obj1, obj2, obj3](这样objX={number:X} )。当我在class1中更改一个项目,例如:myVar[0]={number:5}时,更改将不会显示在我的class2 myLocalVar中,而myLocalVar[0].number将等于1。但是,class2的myVar发生了变化......似乎this.myLocalVar.push(this.myVar[int]);创建了一个深层副本而不是浅层副本。

Typescript是否会改变Javascript中push的行为?如果是,我该怎么做才能保留参考文献并做一个浅层复制?

代码示例

@Injectable()

export class Class1{

    public myVar:any[];

    constructor(){
        this.myVar = [{number: 1}, {number: 2}, {number: 3}];
    }

    changeVar(newVar):void{
        this.myVar[0] = newVar; // newVar = {number: 5}
    }
}
@Component({
    selector: 'class2',
    viewInjector: [Class1],
    templateUrl: 'someURL'
})
export class Class2{

    private myLocalVar:any[] = [];

    constructor(class1: Class1){
        this.myVar = class1.myVar;
    }

    showVars():void{
        console.log(this.myLocalVar[0]);
        console.log(this.myVar[0]);
    }

    ngOnInit(){
        for(let int = 0; int < this.myVar.length; int++){
            this.myLocalVar.push(this.myVar[int]);
        }
    }
}

console.log将打印两个不同的值:console.log(this.myLocalVar[0])打印1console.log(this.myVar[0]);打印5后,第三个人调用changeVar()党!

修改

以下是展示问题的plunker

  • 点击显示,检查您的控制台,您将看到相同的值
  • 点击更改
  • 再次点击显示,您会看到myVarmyLocalVar
  • 的两个不同值

我需要的是每次更改myVar[x]=newObj我希望myLocalVar反映这一变化。如果您希望验证答案,请提供该问题的解决方案。

4 个答案:

答案 0 :(得分:0)

更改

ngOnInit(){
    for(let int = 0; int < this.myVar.length; int++){
        this.myLocalVar.push(this.myVar[int]);
    }
}

ngOnInit(){
  this.myLocalVar = this.myVar;
}

在第一个仅复制数组元素的引用。在数组的第二个引用被复制?

答案 1 :(得分:0)

您的意图似乎是更新对象的值,而是创建一个新对象并将该新对象插入到原始数组中(仅限)。

这将按照您的意图行事:

changeVar(newVar: Object): void {
    this.myVar[0].number = newVar.number;
}

您链接的plunker代码与发布的代码不同步。在plunker的情况下,你传递一个数字,而不是一个对象。它有:

changeVar(newVar): void {
    this.myVar[0] = {number:newVar}; // newVar = {number: 5}
}

在这种情况下,请更改为:

changeVar(newVar: number): void {
    this.myVar[0].number = newVar;
}

答案 2 :(得分:0)

“Object.assign”执行浅拷贝。

(<any>Object).assign(this.shallowCopyObject, this.myObject);

答案 3 :(得分:0)

您遇到此问题,因为cv::erode(image, result, cv::Mat()); myLocalVar是两个不同的引用。意思是,它们是两个不同的数组容器

当您将元素从myVar推送到myVar时,您将myLocalVar中元素的引用推送到myVar。所以 如果

myLocalVar你有两个对象,两个对象的引用都被推送到myVar = [{name: 1}, {name: 2}]

当您调用myLocalVar方法时,基本上用新对象引用替换changeVar中的元素引用。但是,对要替换的元素的旧引用仍然存在并由myVar引用,因此您看到了结果。

那么解决方案呢?

您需要更改myLocalVar方法设置值的方式。你应该做changeVar而不是this.myVar[0] = {number:newVar};。这样可以保持参考。

相关问题