范围问题-更改回调中的数据正在更改更高的范围

问题描述 投票:0回答:1

我正在构建一个小型d&d应用程序,以练习按角度传递数据组件,但遇到了一个奇怪的问题。

我从API调用中获得了一个“怪物”对象,然后将其填充到视图中一定次数。我试图通过添加索引来更改值之一“名称”-简单-获取“名称”添加和索引。我正在获取更改它的“名称”的值,然后将其推入组件中的数组-一切正常。我认为循环的下一次迭代的原始值应该保持不变,但事实并非如此。我在这里不了解范围。

试图只发布一些代码,因为我知道问题在哪里,而且我知道它是一个范围问题,我只是想知道为什么这是一个概念,因为它是我不熟悉的东西。使用

export class CombatComponent implements OnInit {
  selected:number;
  monsters:any[] = []
  addedMonsters:any[] =[]

  monsterNumber:number = 0;    <----this is being passed from a form - its working

  constructor( private ms:MonsterService) { }

 <-dont want to post the entire function because this is where the issue lies ->

this.$monsterData.subscribe(data =>{
 this.currentMonster=data;

 for (let i = 0 ; i<this.monsterNumber; i++){

   let originalName = this.currentMonster.name;
   console.log(this.currentMonster.name)

   this.monsters.push(this.currentMonster)
   let newName = this.monsters[i]['name'] = this.currentMonster.name +" " + `${i+1}`
   this.monsters[i].name = newName

   console.log(this.monsters)

 }

我的问题是,在第一次迭代之后,我认为应该发生的是一个带有名称+索引的数组。真正发生的是,第二次通过currentMonster的“名称”值更改为原始值+索引。我在这里不了解的范围是什么?

javascript typescript scope global
1个回答
0
投票

您每次迭代都将同一个怪物对象推入数组。这将导致数组元素,例如this.monster[1]this.monster[2]彼此保持相同的对象。因此,如果您更改monster[1],那么您也在更改monster[2],依此类推(包括currentMonster,因为它们都引用同一个对象)

我假设您实际上是在尝试根据currentMonster属性创建新的怪物对象,并尝试为其分配新的名称。

//these do shallow copy of the properties

//using spread operator to create new object
let newMonster = {...this.currentMonster}
//using Object.assign() to create new object
let newMonster = Object.assign({},this.currentMonster);

然后只需更改适当的属性,然后将新对象推入数组。

//give new monster a name 
newMonster.name = this.currentMonster.name +" " + `${i+1}`;

//push the new monster on the array
this.monsters.push(newMonster);

0
投票

var arr = []; // create arry 
var obj = {ima:"object"}; // create object
arr.push(obj); // pass same object 3 times
arr.push(obj);
arr.push(obj);

console.log(arr); // log arr 
// will print : [
// {
//  /**id:2**/
//    "ima": "changed object"
//  },
//  /**ref:2**/,
//  /**ref:2**/
// ]
obj.ima = "changed object"; // change the object 

console.log(arr); // log the array, notice that object inside the array will be modified

arr[0].ima = "changed in the arr"; // then modify the object inside the array

console.log(obj); // notice original object will be modified.

上面的代码与您在代码中所做的相同。您传递的是引用而不是复制的值。


0
投票

执行此操作时:

 this.monsters.push(this.currentMonster)

您没有将currentMonster对象的副本推送到要推送对该对象的引用的数组。这意味着:

 this.monsters[0] === this.currentMonster

因此,当您更改name属性时:

this.monsters[i].name = newName

您也正在更改currentMonster.name属性

您可能想要做的是创建currentMonster对象的副本并仅更改名称:

this.monsters.push({
     ...this.currentMonster,
     name: this.currentMonster.name +" " + `${i+1}`
})
© www.soinside.com 2019 - 2024. All rights reserved.