JavaScript 变量在没有指令的情况下写入其他变量

JavaScript Variables writing to other variables with no instruction?

本文关键字:变量 情况下 其他 指令 JavaScript      更新时间:2023-09-26

我不知道如何解释这一点,这真的很困扰我。它弄乱了我的很多代码。无论如何,这里基本上就是这样。假设我有一个变量,它保存了一个带有一些值的结构,比如默认设置:

var DefaultValues = {
    username: "cakeisajoke",
    this: "is some",
    default: {
        data: 483
    },
    lives: 3,
    playerX: 0,
    playerY: 0
}

在我的代码中,我使用此变量作为"模板",因此我可以更轻松地重置游戏。喜欢这个:

var GameValues = DefaultValues;

好的,到目前为止这是有道理的。现在,假设玩家失去了生命:

GameValues.lives--;

或者,玩家移动一些:

GameValues.playerX += 20;
GameValues.playerY -= 10;

所以,现在我的游戏值发生了变化,我将游戏设置为这个。但是,然后玩家失败了,游戏结束了。如果他想再次玩,我所要做的就是将 GameValues 变量重置为默认值:

GameValues = DefaultValues;

而且,就我而言,这应该只是将游戏值设置为默认值,对吧?但是,事实并非如此。出于某种原因,游戏值和默认值现在具有相同的值,而它们不应该具有相同的值。例如,默认值现在是 0,而不是原来的 1。

为什么要这样做?我看了又看了一遍,除了那个初始结构之外,我没有在代码中的任何位置设置 DefaultValues。

"我用这个和默认值作为例子,我知道我实际上不能使用它们,因为它们是保留的"

这是因为javascript使用对象的引用。因此,将一个对象分配给另一个对象只会使它们指向同一对象。您需要克隆对象,此线程描述了几种方法。

var GameValues = DefaultValues; //Both variables reference the same object
GameValues.lives--; //Since they both reference the same object this will change both the variables so to say

还要考虑不要使用单词 thisdefault 作为键,它们是保留关键字。

创建 DefaultValues 对象时,会在内存中创建一个对象,并在 DefaultValues 变量中创建对该对象的引用

+---------------+ +-------------------------+|默认值 |--------------->|用户名: "蛋糕樱桃" |+---------------+                |生命数: 3 |                                 |(等等) |                                 +-------------------------+

执行此操作时:

var GameValues = DefaultValues;

您只需将对对象的引用存储在第二个变量中。现在你有这个:

+---------------+|默认值 |---++---------------+   |           +-------------------------+                    |           |用户名: "蛋糕樱桃" |                    +----------->|生命数: 3 |                    |           |(等等) |+---------------+   |           +-------------------------+|游戏价值 |---++---------------+

您没有DefaultValues的副本,您只有对对象的两个引用。对对象所做的更改会更改对象,因此无论使用哪个引用,自然可见。

您当前的问题是因为javascript使用对象的引用。

对于这种方法之王,您可以使用其他 js 模式,如下所示

var DefaultValues = {
    username: "cakeisajoke",
    "this" : "is some",
    default: {
        data: 483
    },
    lives: 3,
    playerX: 0,
    playerY: 0
}
var GameValues =  Object.create(DefaultValues);

你可以做到

GameValues.lives--;
GameValues.playerX += 20;
GameValues.playerY -= 10;

没有改变定义。

值得一看的是,这个基于

javascript浏览器的游戏的建模模式是值得的

因为

DefaultValues是一个对象,所以当你把它分配给GameValues时,你实际上只是在分配对它的引用,而不是复制对象本身。这意味着当您设置一个属性时,更改将反映在另一个属性中。

您可以通过将属性从DefaultValue复制到GameValue而不是在一个分配中执行此操作来解决此问题。下面是一个基本示例,但请注意,您还必须处理嵌套对象:

Object.keys(DefaultValues).forEach(function (key) {
    GameValues[key] = DefaultValues[key];
});

当你做赋值var a = {}时,JavaScript 存储在a对新创建对象的引用中,而不是它的值,这就是为什么当你通过 GameValues 更改设置时,DefaultValues中的设置也会发生变化:这两个是对同一对象的引用。

当您初始化基元类型的新变量(例如 var i = 1; )时,它会i存储实际值,因此

var i = 1;
var b = i;
var b += 4; // b is 5, i is still 1   

为了解决您的特定任务,您可以编写一个递归函数,该函数将遍历对象,并复制每个键值对。请参阅本文,它应该为您提供有关如何执行此操作的一些见解。