Мои объекты класса со случайными значениями получают те же самые значения - PullRequest
0 голосов
/ 01 марта 2020

Я пытаюсь создать несколько объектов с различными рандомизированными значениями со структурой из файла JSON. Для каждого нового объекта, который я создаю, я по какой-то причине получаю те же рандомизированные значения, что и первый объект.

Я делаю это, создавая объект через класс. Я поместил каждый «Thingy», созданный в массиве для дальнейшего использования. Файл JSON заполняется атрибутами, которые должны каждый раз при создании нового Thingy получать случайное значение от 0 до 10. Занятия - не моя сильная сторона, я рад услышать лучшие способы сделать это (я заинтересован в том, чтобы в Thingies позже были функции).

Когда я перезагружаю страницу и создаю новую Thingy, при нажатии моей кнопки значения красиво рандомизированы. Проблема в том, что каждый раз, когда я нажимаю кнопку, чтобы создать больше Thingies, имя рандомизируется, НО каждое значение получает те же случайные значения, что и предыдущий Thingy. Сначала я подумал, что это проблема с Javascript использованием генератора псевдослучайных чисел, но теперь я считаю, что у меня неправильное понимание на уровне языка сценариев.

Может кто-нибудь пролить свет на то, что я делаю неправильно или нет понимания?

Пожалуйста, скажите мне, если я должен предоставить больше информации, это мой первый пост!

КОД:

var i;
var names = ["bjorn", "agnetha", "benny", "annifrid"];
var thingies = [];

var jsonFile = {
  "bodyA": {
      "sub1": {
          "subsub1": null,
          "subsub2": null,
          "subsub3": null
      },
      "sub2": {
          "subsub1": null,
          "subsub2": null
      },
      "sub3": {
          "subsub1": {
              "subsubsub1": null,
              "subsubsub2": null,
              "subsubsub3": null
          }
      }
  },
  "bodyB": {
      "sub1": {
          "subsub1": null
      }
  },
  "bodyC": null
}

class Thingy {
  constructor (name, attributes) {
      this.name = name;
      this.attributes = attributes;
  }
}

var button = document.createElement("input");
  button.type = "button";
  button.value = "Create new thingy";
  button.onclick = function() {
      // I'm using the math.js to get a random value from the names array (Yes, in this debugging instance it could get the same name as other Thingies)
      thingy = new Thingy(math.pickRandom(names), getAttributes(jsonFile));
      thingies.push(thingy);
      console.log(thingy.name + " was created!");
  }
  document.getElementById("myDiv").appendChild(button);

function getAttributes(json) {
  function iterateObject(json) {
      Object.keys(json).forEach(function (k) {
          if (json[k] !== null && typeof json[k] === 'object') {
              iterateObject(json[k]);
              return;
          }
          if (json[k] === null) {
              // This is where I get the exact same values everytime I create a new Thingy after the first one
              json[k] = math.randomInt(0, 10); // (Also from math.js - very similiar to default Math)
          }
      });
      return json;
  }
  return iterateObject(json);
}

function logThingies() {
  for (i = 0; i < thingies.length; i++) console.log(thingies[i]);
}
<head>
    <!-- math.js -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/6.6.1/math.js"></script>
</head>
<body>
    <div id="myDiv">
        <button onclick="logThingies()">Show me all!</button>
    </div>
</body>

1 Ответ

0 голосов
/ 01 марта 2020

Поскольку вы создаете случайное значение только при json[k] === null, а затем присваиваете это случайное значение json[k], поэтому json[k] никогда не будет снова null.

В JavaScript, все объекты передаются / присваиваются по ссылке. Это означает, что когда у вас есть объект и вы присваиваете этот объект другой переменной или передаете объект другой функции в качестве аргумента, переменная / функция получит тот же объект, который вы передали, а не его копию, и модифицирует объект Полученный будет модифицировать «базовый» объект, который вы передали ему, так же как и тот же объект.

Проверьте этот тест:

var obj = {
    test: 1
};

var obj2 = obj;

console.log("obj.test:", obj.test);
console.log("obj2.test:", obj2.test);

obj.test = 2;

console.log("obj.test:", obj.test);
console.log("obj2.test:", obj2.test);

Короче говоря, все ваши атрибуты Thingies являются ссылкой на один и тот же объект, помещенный в одно и то же пространство памяти.

То, что вы на самом деле хотите сделать, это например, чтобы создать копию объекта с чем-то вроде этого (я только что немного изменил ваш код):

function getAttributes(json) {
  var ret = {};
  function iterateObject(ret, json) {
      Object.keys(json).forEach(function (k) {
          if (json[k] !== null && typeof json[k] === 'object') {
              iterateObject(ret[k] = {}, json[k]);
          } else if (json[k] === null) {
              // This is where I get the exact same values everytime I create a new Thingy after the first one
              ret[k] = math.randomInt(0, 10); // (Also from math.js - very similiar to default Math)
          } else {
              ret[k] = json[k];
          }
      });
  }
  iterateObject(ret, json);
  return ret;
}

Обратите внимание, как я создаю новый объект каждый раз, когда json[k] объект. Таким образом, вы всегда получите новый чистый объект без изменения json.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...