JavaScript再次变得神秘吗?

时间:2019-06-05 16:57:47

标签: javascript angular typescript karma-jasmine

我有一个angular服务,它具有两个相同类型的属性。我将相同的对象以相反的顺序推向它们以进行测试。但是,当我更改一个数组中的对象之一时,我看到相同的代码也更改了第二个数组中的相同对象。问题是我什至没有提到代码中的第二个数组。这是我的服务班级:

self.request

我的会议界面:

class Myservice {

  public meetings : Meeting [];
  public participated : Meeting [];

  constructor(){
      this.meeting = [];
      this.participated = [];
  }

  create(participants, id){

       let meeting : Meeting = {
          id : id,
          participants : participants
       }

      this.meetings.push(meeting);
      this.participated.unshift(meeting);
  }

  addParticipant(userId : number, meetingId : number){
      this.meetings.forEach((meeting : Meeting) => { 
         if(meeting.id == meetingId)  {
           meeting.participants.push(userId)
         } 
      })
  }


}

这是我的测试方式:

interface Meeting {
     id : number;
     participants : Array<number>;
}

该测试通过了,但日志显示:

describe('My service', () => {

     let provider : Myservice;

     beforeEach( () => {
        provider = new Myservice();
     });

     it('should add a participant to the participants', () => {

        provider.create([2], 1);
        provider.create([2], 2);
        provider.create([2], 3);
        provider.create([2], 4);

        provider.addParticipant(6, 3);

        expect(provider.meetings[2].participants).toEqual([2,6])  
        //expect(provider.participated[1].participants).toEqual([2,6])  

        console.log('meeting par :', provider.meetings[2].participants)
        console.log('Partic par :', provider.participated[1].participants)
     })

正如我们所见,参与数组中的对象也已更改为:O。你们知道为什么吗?我的业力/茉莉花版本是:

LOG: 'meeting par :', [2, 6]
LOG: 'Partic par :', [2, 6]

编辑。 "@types/jasmine": "^3.3.13", "@types/node": "^12.0.4", "angular2-template-loader": "^0.6.2", "core-js": "^3.1.3", "html-loader": "^0.5.5", "istanbul-instrumenter-loader": "^3.0.1", "jasmine": "^3.4.0", "jasmine-spec-reporter": "^4.2.1", "karma": "^4.1.0", "karma-chrome-launcher": "^2.2.0", "karma-coverage-istanbul-reporter": "^2.0.5", "karma-jasmine": "^2.0.1", "karma-jasmine-html-reporter": "^1.4.2", "karma-sourcemap-loader": "^0.3.7", "karma-webpack": "^3.0.5", "null-loader": "^2.0.0", "protractor": "^5.4.2", "ts-loader": "^3.0.3", "ts-node": "^3.0.2", "typescript": "~2.6.2" "@angular/compiler": "5.2.11", "@angular/compiler-cli": "5.2.11", "@angular/core": "5.2.11", 函数的新形式也给出了相同的响应:

create

2 个答案:

答案 0 :(得分:3)

您要通过引用两个数组来推送相同的对象。那就是你问题的原因。您应该为每次推送创建一个新对象,或者克隆该对象。

更新#1

我发现的第二个潜在问题是您的participants数组。

在JS数组中,对象以及对象在简单分配时都通过引用传递。

对于简单对象,可以使用Object.assign,对于简单数组,可以使用[..].slice()

另一种克隆方式是 var a = {...myObj}用于对象,var b = [...myArr]用于数组。

这些方法是用于简单克隆的,无法正确克隆嵌套的对象/数组。因此,您需要编写一个递归克隆函数或使用Lodash中的cloneDeep,该函数与数组和对象都兼容。

答案 1 :(得分:3)

因此,请查看您的代码:

create(participants, id){
  let meeting : Meeting = {
    id : id,
    participants : participants
  }

  this.meetings.push(meeting);
  this.participated.unshift(meeting);
}

您正在创建一个对象,并将该对象推入两个不同的位置。当您将这些对象推入这些数组时,您给这些数组的对象不是副本,而是对其的引用。

在内存中,仅存在一个meeting,并且在meetingsparticipated数组中有一个引用。因此,当您将meeting放入addParticipant内时,就是在修改该对象,并且是唯一的meeting对象。

JavaScript并不是神秘的,可以将其视为引用对象而不是对象本身的数组。

此外,participants数组也是具有两个引用的对象。如果希望每个实例上都有该阵列的副本,则可以将其散布到新的阵列中。 here。可以看到使用扩展语法复制数组的示例以及如何在数组中使用扩展语法。

要解决此问题,您可以在每次按下数组时创建一个新对象,同时将参与者数组散布到一个新对象中以创建一个新的参与者数组:

  this.meetings.push({id: id, participants: [...participants]});
  this.participated.unshift({id: id, participants: [...participants]});

或者,您可以使用对象文字的简写形式,因为它们为id属性使用相同的名称:

  this.meetings.push({id, participants: [...participants]});
  this.participated.unshift({id, participants: [...participants]});

这样,每个数组都有对不同对象的引用,并且每个participants数组在Meeting对象中也是唯一的。

希望有帮助!

编辑1:在发现提供的代码中存在多个问题之后,添加了更多详细信息

编辑2:在价差运算符上添加了资源,并在数组上使用了