Context
I'm using Typescript/Angular2 RC1 for my webapp and I have two classes. In class1 (Angular2 service), I have a variable myVar = [obj1, obj2, obj3]
and in class2 (Angular2 component), I get myLocalVar = class1.myVar
in the constructor using viewInjector
to inject the service.
Problem
In class2, I copy myVar
with a push
(shallow copy because it copies objects) so myLocalVar
is equal to [obj1, obj2, obj3]
(such that objX={number:X}
). When I change one item such as: myVar[0]={number:5}
in class1 the change won't appear in my class2 myLocalVar
and myLocalVar[0].number
will be equal to 1
. However, myVar
of class2 changes... It seems that the this.myLocalVar.push(this.myVar[int]);
created a deep copy instead of a shallow copy.
Is Typescript changing the behavior of a push
in Javascript? If yes, what should I do to keep the reference and do a shallow copy?
Code Sample
@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]);
}
}
}
The console.log
will print two different values: console.log(this.myLocalVar[0])
prints 1
and console.log(this.myVar[0]);
prints 5
after changeVar()
has been called by a third party!
Edit
Here is a plunker that demonstrates the problem:
myVar
and myLocalVar
What I need is each time I change myVar[x]=newObj
I want myLocalVar
to reflect that change. Please include a solution to that problem if you want your answer to be validated.
Change
ngOnInit(){
for(let int = 0; int < this.myVar.length; int++){
this.myLocalVar.push(this.myVar[int]);
}
}
to
ngOnInit(){
this.myLocalVar = this.myVar;
}
In the first only reference of the array elements is copied. In the second reference of array is getting copied?
Your intent seems to be to update an object's values, but instead you are creating a new object and inserting that new object into the original array (only).
This will do what you intended:
changeVar(newVar: Object): void {
this.myVar[0].number = newVar.number;
}
The plunker code you linked to is not in sync with the posted code. In the plunker's case, you are passing a number, not an object. It has:
changeVar(newVar): void {
this.myVar[0] = {number:newVar}; // newVar = {number: 5}
}
In that case, change to:
changeVar(newVar: number): void {
this.myVar[0].number = newVar;
}
“ Object.assign”执行浅表副本。
(<any>Object).assign(this.shallowCopyObject, this.myObject);
Your have this problem because myLocalVar
and myVar
are two different references. Meaning, they are two different array containers .
And when you push element from myVar
to myLocalVar
, you push the references of the elements in myVar
into myLocalVar
. So if
myVar = [{name: 1}, {name: 2}]
you have two object in it and both references to the objects are pushed into myLocalVar
.
When you call changeVar
method, you basically replace the element reference in myVar
with new object reference. However, the old reference to the element being replaced is still there and referenced by myLocalVar
, thus the result you see.
So the solution?
You need to change how your changeVar
method set the value. Instead of doing this.myVar[0] = {number:newVar};
, you should do this.myVar[0]['number'] = newVar;
This maintains the reference.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.