Изменение копии объекта Javascript приводит к изменению исходного объекта в реактивных формах Angular 5.

Я пытаюсь создать копию моего объекта значения реактивной формы (с оператором распространения или Object.assign) и применить к нему некоторые изменения перед отправкой на мой сервер.

Это код, который создает мою форму, и он работает, как и ожидалось, в моем шаблоне:

newTask: FormGroup

this.newTask = this.formBuilder.group({
      partner:              [null, [Validators.required]],
      title:                [null, [Validators.required, Validators.minLength(5), Validators.maxLength(50)]],
      description:          [null, [Validators.minLength(10), Validators.maxLength(120)]],
      responsible:          [null, [Validators.required]],
      type:                 [null, [Validators.required]],
      priority:             [null, [Validators.required]],
      status:               [null, [Validators.required]],
      history:              this.formBuilder.array([])
    })

В приведенном ниже коде показано, как я могу добавлять и удалять элементы из моего массива истории:

createAction (action?) {
    return this.formBuilder.group({

      title: [action ? action.title : undefined, [Validators.required, Validators.minLength(5), Validators.maxLength(50)]],
      description: [action ? action.description : undefined, [Validators.required, Validators.minLength(10), Validators.maxLength(200)]],
      resolveAt: [action ? action.resolveAt : undefined],
      result: [action ? action.response : undefined, [Validators.minLength(10), Validators.maxLength(200)]],
      resolvedAt: [action ? action.resolvedAt : undefined],
      status: [action ? action.status : undefined, [Validators.required]],
      relatedPerson: [action ? action.relatedPerson : undefined]

    })
  }

  addAction (action?): void {
    const history = this.newTask.get('history') as FormArray
    history.push(this.createAction(action || initialActionState))
  }

  removeAction (i: number): void {
    const history = this.newTask.get('history') as FormArray
    history.removeAt(i)
  }

После того, как пользователь правильно ввел все необходимые данные, когда я отправляю свою форму, это модификация, которую я должен выполнить:

let cleanVar = {...this.newTask.value}
// I could also use let cleanVar = Object.assing({}, this.newTask.value), the result is the same
    cleanVar.history.forEach(item => {
      item.status = item.status.string
      if (item.relatedPerson) item.relatedPerson = item.relatedPerson._id
    })
console.log(this.newTask.value)

Как видите, я пытаюсь изменить копию исходного объекта, но когда я регистрирую this.newTask.value, изменения распространяются и на него.

У меня никогда не было подобных проблем с копиями объектов, поэтому я пытаюсь выяснить, почему это происходит. Может быть, это что-то связанное с Angular Reactive Forms, что я не могу обнаружить.

Кто-нибудь знает, почему это происходит?

Спасибо!

Обновить

Вот что находится внутри моей переменной newTask.value:

введите здесь описание изображения


person Felipe Micali    schedule 11.05.2018    source источник
comment
Копии нет. В этой строке let cleanVar = {...this.newTask.value} cleanVar становится ссылкой на литерал объекта, который, в свою очередь, имеет (ссылки на) «исходные» элементы из newTask.value.   -  person marekful    schedule 11.05.2018
comment
Спасибо за Ваш ответ. Так как же мне создать копию моего объекта? Я думал, что оператор распространения и Object.assign создают копии без ссылок... А в других случаях я смог этого добиться, только когда я пытаюсь скопировать значение реактивной формы, это происходит.   -  person Felipe Micali    schedule 11.05.2018
comment
Можете ли вы поделиться тем, что внутри newTask.value?   -  person marekful    schedule 11.05.2018
comment
Конечно, это в обновленной версии моего вопроса.   -  person Felipe Micali    schedule 11.05.2018
comment
Если у вас есть доступ к библиотеке lodash в вашем проекте, вы можете просто использовать _.cloneDeep(objectToClone), которая вернет вам новую копию. lodash.com/docs#cloneDeep   -  person Rikin    schedule 11.05.2018
comment
Возможный дубликат Что является альтернативой angular.copy в Angular   -  person Rikin    schedule 11.05.2018
comment
Клонировать массивы в JS сложно. Если все элементы являются примитивными значениями, вы можете добиться этого с помощью splice(), но тогда элементы объекта все равно будут ссылками. Lodash — хороший выбор, так как он также позаботится об объектах.   -  person marekful    schedule 11.05.2018
comment
Удивительно, попробовал и все получилось! Всем большое спасибо!   -  person Felipe Micali    schedule 11.05.2018


Ответы (1)


Как предложили marekful и Rikin, лучше всего использовать lodash cloneDeep:

import { cloneDeep } from 'lodash'

let clonedVar = cloneDeep (originalVar)

// do whatever you need with clonedVar and originalVar isn't touched

Спасибо всем!

person Felipe Micali    schedule 11.05.2018