Javascript将对象推入数组会改变整个数组

Javascript将对象推入数组会改变整个数组,javascript,arrays,object,Javascript,Arrays,Object,我正在使用一个特定的游戏制作框架,但我认为这个问题适用于javascript 我试图制作一个叙述脚本,这样玩家就可以在屏幕底部看到“兽人打你了”。我想一次显示最后4条消息,如果玩家愿意的话,可以让他们回过头来查看日志中的30-50条消息。为此,我设置了一个对象和一个数组,将对象推入其中 所以我最初设置了一些变量,像这样 servermessage: {"color1":"yellow", "color2":"white", "message1":"", "message2":""}, serve

我正在使用一个特定的游戏制作框架,但我认为这个问题适用于javascript

我试图制作一个叙述脚本,这样玩家就可以在屏幕底部看到“兽人打你了”。我想一次显示最后4条消息,如果玩家愿意的话,可以让他们回过头来查看日志中的30-50条消息。为此,我设置了一个对象和一个数组,将对象推入其中

所以我最初设置了一些变量,像这样

servermessage: {"color1":"yellow", "color2":"white", "message1":"", "message2":""},
servermessagelist: new Array(),
当我通过操纵servermessage.color1对事件调用的不同数据多次使用此命令(如下所示)时。信息1等

servermessagelist.push(servermessage)
它会用该数据的副本覆盖整个阵列。。。你知道为什么吗?我能做些什么

因此,如果我按下color1“红色”和message1“漫游者”按钮。。如果我按下按钮,数据是正确的
color1“黄色”和message1“总线”数据是。color1:“黄色”的两个副本。message1:“总线”

servermessagelist:new Array()每次执行时都会清空数组。最初初始化数组时只执行该代码一次。

servermessage
推入
servermessagelist
时,实际上(或多或少)是在推送对该对象的引用。因此,对
servermessage
所做的任何更改都会反映在引用它的任何地方。听起来您想要做的是将对象的克隆推送到列表中

声明一个函数,如下所示:

function cloneMessage(servermessage) {
    var clone ={};
    for( var key in servermessage ){
        if(servermessage.hasOwnProperty(key)) //ensure not adding inherited props
            clone[key]=servermessage[key];
    }
    return clone;
}
然后,每次您要将消息推送到列表中时,请执行以下操作:

servermessagelist.push( cloneMessage(servermessage) );

将对象添加到数组时,它只是对所添加对象的引用。将对象添加到数组中不会复制该对象。因此,当您稍后更改对象并再次将其添加到数组中时,您只需要拥有一个数组,其中包含对同一对象的多个引用

为阵列中的每个添加创建一个新对象:

servermessage = {"color1":"yellow", "color2":"white", "message1":"", "message2":""};
servermessagelist.push(servermessage);
servermessage = {"color1":"green", "color2":"red", "message1":"", "message2":"nice work"};
servermessagelist.push(servermessage);

我也有同样的问题。我有一个复杂的物体,我正在推进到阵列中。我所做的;我使用JSON.stringify()将JSON对象转换为字符串,并将其推入数组

当它从数组返回时,我只是使用JSON.parse()将该字符串转换为JSON对象

这对我来说很好,虽然这是一个更全面的解决方案。
如果你们有其他选择的话,就在这里发帖子吧

我不知道为什么还没有人建议使用JSON方法来实现这一点。 您可以首先对对象进行字符串化,然后再次对其进行解析以获得对象的副本

让uniqueArr=[];
let referencesArr=[];
设obj={a:1,b:2};
uniqueArr.push(JSON.parse(JSON.stringify(obj));
参考启动推力(obj);
目标a=3;
对象c=5;
uniqueArr.push(JSON.parse(JSON.stringify(obj));
参考启动推力(obj);
//您可以在控制台日志中看到差异
控制台日志(uniqueArr);

console.log(referencesArr)此解决方案也适用于包含嵌套键的对象

在推动之前,通过以下方式将obj拉紧:

JSON.stringify(obj)
当您使用时,通过

JSON.parse(obj);

在将对象推入数组之前,有两种方法可以使用深度复制对象。 1.按对象方法创建新对象,然后推送它

servermessagelist = []; 
servermessagelist.push(Object.assign({}, servermessage));
  • 通过JSON stringigy方法创建对象的新引用,并使用parse方法推送它

    servermessagelist=[];
    servermessagelist.push(JSON.parse(JSON.stringify(servermessage));


  • 此方法对于嵌套对象非常有用。

    正如上面多次提到的,最简单的方法是将其设置为字符串并将其转换回JSON对象

    this.<JSONObjectArray>.push(JSON.parse(JSON.stringify(<JSONObject>)));
    
    this..push(JSON.parse(JSON.stringify());
    

    工作起来很有魅力。

    消息列表在我的初始函数中,推送在websocket事件上运行的更新函数中……啊,我的错,我没有从您的代码示例中了解到。但正如nbrooks所说,在javascript中,对象总是作为引用传递,这就是它不能正常工作的原因。你是什么意思“使用该数据的副本覆盖整个阵列"?你能展示你用来迭代结果数组的代码吗?有可能重复的吗?有没有更简单的方法可以通过声明一个对象数组来做到这一点?我不知道怎么做。每次你要推送
    servermessage
    ,你都必须做这个克隆。一旦你改变它,克隆它,然后推送它的克隆。你可以声明每次使用第一个对象的属性并将值设置为
    null
    或'@user1481372'时,新对象的编辑版本可能更容易实现。
    cloneMessage
    您可以使用逐字记录。将推送语句替换为我在任何地方都有的语句。这只会为您创建消息的克隆。T他是唯一对我有效的东西。我需要在多维循环中将数组推入另一个数组。我想利用增量推入状态,但发现所有数组都在数组内。与循环结束时的外观类似。我知道词法作用域和闭包,假设它与外部作用域相关sue。我尝试用多种方法在循环中克隆数组,但发现使用JSON.stringify是唯一有效的方法。我假设JSON.stringify基本上克隆了数组,但不确定为什么.splice和.concat对我不起作用。