简体   繁体   中英

Why is the original item in my array being overwritten with Object.assign?

I have a unit test that is producing something I didn't expect:

Background: I'm making a simple todo list with Angular/test driven development.

Problem: When I call editTask on an item in the array, it changes the item's value. But, I don't see how it's changed in the original array because the original array is never accessed in the method I'm testing. Please help me connect HOW the original array is being changed? It seems Object.assign is doing this, but why?

 describe('editTask', () => {
    it('should update the task by id', () => {
      const dummyTask1 = { id: 1, name: 'test', status: false };
      service.tasks.push(dummyTask1); //refers to TestBed.get(TaskService)
      const id = 1;
      const values = { name: 'cat', status: false };

      service.editTask(id, values);
      console.log(service.tasks); // why does this log this object? [Object{id: 1, name: 'cat', status: false}]
      expect(service.tasks[0].name).toEqual(values.name); // Test passes
    });
  });

Here is the method I'm testing:

  editTask(id, values) {
    const task = this.getTask(id);

    if (!task) {
      return;
    }

    Object.assign(task, values); //How does this line change the array?

    return task;
  }

  getTask(id: number) {
    return this.tasks.filter(task => task.id === id).pop(); //is this altering the original array somehow?
  }

If needed, here's the full Angular service:

export class TaskService {
  tasks: any = [];
  lastId = 0;

  constructor() { }

  addTask(task) {
    if (!task.id) {
      task.id = this.lastId + 1;
    }

    this.tasks.push(task);
  }

  editTask(id, values) {
    const task = this.getTask(id);

    if (!task) {
      return;
    }

    Object.assign(task, values);

    return task;
  }

  deleteTask(id: number) {
    this.tasks = this.tasks.filter(task => task.id !== id);
  }

  toggleStatus(task) {
    const updatedTask = this.editTask(task.id, { status: !task.status});

    return updatedTask;
  }

  getTasks() {
    return of(this.tasks);
  }

  getTask(id: number) {
    return this.tasks.filter(task => task.id === id).pop();
  }
}

Here is the github repo: https://github.com/capozzic1/todo-tdd

The getTask() method is getting a reference to the item in the array using the array filter() method.

It then uses Object.assign() to change the properties of the item. The Object.assign() method is used to copy the values of all enumerable own properties from one or more source objects to a target object. It will return the target object.

So now the values of the reference in memory of the item is changed. Because it is a reference in memory you will see the original item being changed.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM