为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

月关宝盒 2022-01-07 16:37:30
我正在构建一个小 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 的“名称”值更改为原始值 + 索引。我在这里不理解范围是什么?
查看完整描述

3 回答

?
米脂

TA贡献1836条经验 获得超3个赞

每次迭代都将相同的怪物对象推送到数组上。这会导致数组元素喜欢this.monster[1]和this.monster[2] 彼此持有相同的对象。因此,如果您更改,monster[1]您正在更改monster[2]等等(包括currentMonster因为它们都引用同一个对象)


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


//these do shallow copy of the properties

//this is regular javascript might have to make

//changes to fit typescript syntax


//using spread operator to create new object

//https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax

let newMonster = {...this.currentMonster}

//using Object.assign() to create new object

//https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

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);


查看完整回答
反对 回复 2022-01-07
?
幕布斯7119047

TA贡献1794条经验 获得超8个赞

当你这样做时:


 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}`

})


查看完整回答
反对 回复 2022-01-07
?
HUWWW

TA贡献1874条经验 获得超12个赞

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.


arr.push(Object.assign({},obj)); // this is the copy or use ... operator in typescript


console.log(obj);


arr[1].ima = "something newer";


console.log(obj); // "remains same"


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


查看完整回答
反对 回复 2022-01-07
  • 3 回答
  • 0 关注
  • 149 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信