2016-05-29 6 views
0

КонтекстArray.push выполняет глубокую копию вместо неполную копию

Я использую Машинопись/Angular2 RC1 для моего веб-приложение, и у меня есть два класса. В классе 1 (услуга Angular2) у меня есть переменная myVar = [obj1, obj2, obj3] и в классе2 (компонент Angular2), я получаю myLocalVar = class1.myVar в конструкторе, используя viewInjector для ввода услуги.

Проблема

В class2, я копирую myVar с push (мелкой копии, потому что объекты он копирует) так myLocalVar равно [obj1, obj2, obj3] (например, что objX={number:X}). Когда я меняю один элемент, например: myVar[0]={number:5} в классе1, изменение не будет отображаться в моем классе2. myLocalVar и myLocalVar[0].number будет равно 1. Однако myVar класса2 меняется ... Кажется, что this.myLocalVar.push(this.myVar[int]); создал глубокую копию вместо мелкой копии.

Является ли TypScript изменением поведения push в Javascript? Если да, что мне делать, чтобы сохранить ссылку и сделать мелкую копию?

Пример кода

@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]) отпечатки 1 и console.log(this.myVar[0]); отпечатки 5 после changeVar() был назван третьей стороной!

Редактировать

Вот plunker, который демонстрирует проблему:

  • Нажмите на шоу, проверьте консоль и вы увидите те же самые значения
  • Нажмите на изменение
  • Нажмите на дисплее снова, и вы увидите два разных значения для myVar и myLocalVar

Что мне нужно - каждый раз, когда я меняю myVar[x]=newObj Я хочу myLocalVar, чтобы отразить это изменение. Пожалуйста, включите решение этой проблемы, если вы хотите, чтобы ваш ответ был проверен.

+0

Я думаю, что ваша ошибка заключается в том, что 'push' создает копию. Вы можете легко нажать ту же ссылку на объекты для множества массивов. Попробуйте использовать 'angular.copy()', если вам нужна копия – charlietfl

+0

@charlietfl Я знаю, что 'push' делает мелкую копию, но кажется, что в этом случае она делает глубокую копию! В противном случае, почему я получаю два разных значения? – ncohen

+0

Я никогда не видел 'Array.protoype.push' сделать копию. Я не участвую в машинописных текстах, но сомневаюсь, что он что-то отличает от 'Array'. 'var a = [], b = [], d = {foo: 'bar'}', затем нажмите 'd' в' a' и 'd' в' b' и измените свойство в обоих и наследуется другие, так как они являются ссылками на один и тот же объект – charlietfl

ответ

0

Изменить

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

к

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

В первом только для справки, из элементов массива копируется. Во второй ссылке массива копируется?

+0

Я не могу этого сделать ... мой реальный сценарий заключается в том, что я фильтрую некоторые объекты – ncohen

0

Ваше намерение состоит в том, чтобы обновить значения объекта, но вместо этого вы создаете новый объект и вставляете этот новый объект в исходный массив (только).

Это будет делать то, что вы хотели:

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

код plunker вы связаны не синхронизировано с публикуемым кодом. В случае с плункером вы передаете число, а не объект. Он имеет:

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

В этом случае изменится:

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

"Object.assign" делает неполную копию.

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

Ваш эта проблема, потому что myLocalVar и myVar две разные ссылки. Значение, это два разных контейнера массива.

И когда вы толкаете элемент из myVar в myLocalVar, вы толкаете ссылки элементов в myVar в myLocalVar. Таким образом, , если

myVar = [{name: 1}, {name: 2}] У вас есть два объекта в нем, и обе ссылки на объекты помещаются в myLocalVar.

Когда вы вызываете метод changeVar, вы в основном заменяете ссылку на элемент в myVar ссылкой на новый объект. Однако прежняя ссылка на заменяемый элемент все еще существует и ссылается на myLocalVar, таким образом результат вы видите.

Итак, решение?

Вам нужно изменить способ, которым устанавливается метод changeVar. Вместо того, чтобы делать this.myVar[0] = {number:newVar};, вы должны сделать this.myVar[0]['number'] = newVar; Это поддерживает ссылку.

Смежные вопросы