Javascript: получить объект со случайными значениями свойств - PullRequest
0 голосов
/ 31 декабря 2018

Общее описание

Я ищу способ получить Объект с парой определенных свойств и случайных значений, которые меняются всякий раз, когда я к ним обращаюсь.Также я хочу динамически перезаписать свойства и найти способ получить новый объект.

Контрольный список задач, которые я хочу выполнить

  • Объект имеет рандомизированные значения свойств
  • «новый экземпляр» или новый объект может быть создан с новыми значениями
  • Возможна динамическая замена объекта, и оба вышеуказанных критерия остаются в силе

Кодна основе подробного объяснения

var baseObj = {
    border: Math.round(Math.random() * 10 +3),
    background: 'hsl('+Math.random() * 360 + 'deg 100% 50%)'
}

Таким образом, I baseObj является ссылкой на объект, который остается неизменным .

Другими словами, независимо от того, как часто вы используетеbaseObj или то, как часто вы обращаетесь к его свойствам, значения не изменятся, поскольку Math.random () выполняется и значение присваивается свойству объектов.

Преодолеть эта проблема Я обернул вывод в функцию, которую я могу вызвать, и получил новый Объект с новыми значениями:

var baseObj = () => ({
    border: Math.round(Math.random() * 10 +3),
    background: 'hsl('+Math.random() * 360 + 'deg 100% 50%)'
})

Пока все хорошо, но теперь допустим, что эта функция ожидаетобъектно если его там нет, я буду использовать baseObj по умолчанию.

draw = tempObj => {
    if (!tempObj) {tempObj = baseObj;}
    div.style.borderWidth = tempObj.border + "px";
    div.style.backgroundColor = tempObj.background;
    // missing here merge the two objects
    // missing and main question how to update baseObj with new information
}
draw({
     border: Math.round(Math.random() * 55 + 20)        
})

Точка, в которой я сейчас борюсь, состоит в том, как переписать "шаблон функции baseObj" с шаблономкакого бы значения tempObj не было?

Ожидаемый результат при повторном вызове draw () без каких-либо параметров заключается в том, что вы получите большую границу по меньшей мере 20 и случайный цвет фона.В основном, обновление baseObj новыми правилами того, каким должен быть возвращаемый объект.

Демонстрационная ссылка / Фрагмент

У меня есть ссылка codepen, где я делаю немного больше и объединяю tempObjс baseObj, но я все еще ищу решение той же проблемы.https://codepen.io/Type-Style/pen/VqMMJd?editors=0010

var div = document.querySelector("#div"),
	 getNewStyle = document.querySelector("#getNewStyle"),
	 changeStyle1 = document.querySelector("#changeStyle1"),
	 baseObj = () => ({
		 border: Math.round(Math.random() * 10 +3),
		 background: 'hsl('+Math.random() * 360 + 'deg 100% 50%)'
	 }),
	 enhancementObj = null,
	 getObj = () => (enhancementObj || baseObj()),
	 calculate = (overwriteObj) => {
		 if (!overwriteObj) {
			 var tempObj = getObj();
		 } else {
			 var tempObj = { // merge the two objects
				 ...getObj(),
				 ...overwriteObj
			 }
			 enhancementObj = tempObj; // now I have static values again :-(
		 }
		 draw(tempObj);
	 },
	 draw = tempObj => {
		 div.style.borderWidth = tempObj.border + "px";
		 div.style.backgroundColor = tempObj.background;
	 }

getNewStyle.onclick = () => {draw(getObj())};
changeStyle1.onclick = () => {calculate({
		 border: Math.round(Math.random() * 55 + 20)		
})};
	 
#div {
	width: 300px;
	height: 300px;
	box-sizing: border-box;

	border-style: dashed;
	border-radius: 50%;	
}

/* excuse me using IDs and useless Names in CSS, I know better but this is a JS Question */
<div id="div"></div>
<button id="getNewStyle">getNewStyle</button>
<br>
<button id="changeStyle1">changeStyle1</button>
<p>Press the first button to get random border-size and background color.
The second button should overite the border-size and clicking the first button again should give you a bigger border and random background color, but it doesn't.</p> 

Вопросы / Разное.

Есть ли лучший способ получить новые значения, которые помещают его в функцию?Не стесняйтесь редактировать вопрос, если считаете, что его легче понять.

С новым годом!

Ответы [ 5 ]

0 голосов
/ 08 января 2019

Я выяснил свое недопонимание и неправильное представление об улучшении и случайности свойств.

Предоставив литерал объекта в качестве параметра функции (вычислить):

calculate({
         border: Math.round(Math.random() * 55 + 20)        
})

Границасвойство уже обработано, и нет никакого способа выяснить, что такое вычисление за значением.

Возможные решения, которые фактически будут передавать фабрику в функцию вычисления, так что вы можете получить несколько объектов с одним и тем жерасчеты.

Или благодаря @cgTag и @Bergi и Майку 'Pomax' Kamermans, есть много способов обойти это.

0 голосов
/ 01 января 2019

Я думаю, что самый простой способ - использовать методы объекта и перезаписать их новым объектом.Это дает вам динамические значения и позволяет избежать переопределения геттеров.Единственное, что нужно отметить, это то, что вы должны вызывать методы вместо чтения свойств, т.е. baseObj.border() вместо baseObj.border.

var div = document.querySelector("#div");
getNewStyle = document.querySelector("#getNewStyle");
changeStyle1 = document.querySelector("#changeStyle1");

let baseObj = {
  border: () => Math.round(Math.random() * 10 + 3),
  background: () => 'hsl(' + Math.random() * 360 + 'deg 100% 50%)'
}

const draw = overwriteObj => {
  if (overwriteObj) {
    baseObj = {
      ...baseObj,
      ...overwriteObj
    }
  }
  div.style.borderWidth = baseObj.border() + "px";
  div.style.backgroundColor = baseObj.background();
}

getNewStyle.onclick = () => {
  draw();
};

changeStyle1.onclick = () => {
  draw({
    border: () => Math.round(Math.random() * 55 + 20)
  });
};
#div {
  width: 300px;
  height: 300px;
  box-sizing: border-box;
  border-style: dashed;
  border-radius: 50%;
}
<div id="div"></div>
<button id="getNewStyle">getNewStyle</button>
<br>
<button id="changeStyle1">changeStyle1</button>
0 голосов
/ 31 декабря 2018

Есть ли лучший способ получить новые значения, чем поместить их в функцию?

Нет, функция для получения новых значений (называемая "фабрикой") - самый простой способ.

Суть, с которой я сейчас борюсь, заключается в том, как использовать шаблон для любого tempObj?

Вам просто нужно вызвать функцию:

const randomObj = () => ({
    border: Math.round(Math.random() * 10 +3),
    background: 'hsl('+Math.random() * 360 + 'deg 100% 50%)'
});
function draw(tempObj) {
    if (!tempObj) tempObj = randomObj();
//                                   ^^
    div.style.borderWidth = tempObj.border + "px";
    div.style.backgroundColor = tempObj.background;
}

Кстати, поскольку вы используете ES6, возможно, вы захотите использовать синтаксис параметров по умолчанию:

function draw(tempObj = randomObj()) {
    div.style.borderWidth = tempObj.border + "px";
    div.style.backgroundColor = tempObj.background;
}

Я хочу обновить с новыми правилами то, что он возвращает объектдолжно быть.

Просто сохраните обновление, а не все tempObj (включая случайные дополнения) для улучшения.

let enhancement = {};
function calculate(overwrite) {
    enhancement = {...enhancement, ...overwrite}; // do not merge the randomObj() here!
    const tempObj = {
        ...randomObj(),
        ...enhancement
    };
    draw(tempObj);
}
0 голосов
/ 31 декабря 2018

Я должен признать, что я не совсем понимаю этот вопрос, но, учитывая другие ответы, я подумал, что добавлю другое мнение , и это похоже на мнение вопрос.

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

var baseObj = {
    get border() { return Math.round(Math.random() * 10 +3); },
    get background() { return 'hsl('+Math.random() * 360 + 'deg 100% 50%)'; }
};

console.log(baseObj.border); // prints a random value
console.log(baseObj.border); // prints a different value each time.

Выше приведены случайные значения свойств, но они случайные при каждом чтении.Вы можете заморозить значения путем клонирования объекта.

var frozenObj = Object.assign({}, baseObj); // or {...baseObj}
console.log(frozenObj.border); // prints a value
console.log(frozenObj.border); // prints the same value

Теперь вы можете смешивать вместе разных объектов, чтобы выбрать, какие значения вы хотите случайные.

var example = Object.assign({}, baseObj, {border:999}); // or {...baseObj, border:999}
console.log(example.border); // prints 999
console.log(example.background); // prints a random value, but the same on each call

Теперь я догадываюсь это то, что вы хотели.

0 голосов
/ 31 декабря 2018

Здесь нет ничего сложного: создайте объект или используйте класс, а затем вместо установки свойств «обычным способом» используйте defineProperty , чтобы установить функцию get для любого свойства, которое вы хотитерандомизации.

Итак, давайте воспользуемся классом, потому что его намного проще поддерживать:

import { StringGenerator } from './generators.js';

class MyObj {
  constructor() {
    this.createRandomProperty('background', StringGenerator);
    this.createRandomProperty(..., ...);
    ...
  }

  createRandomProperty(name, generator) {
    let value = generator.newValue();
    Object.defineProperty(this, name, {
      get: () => {
        let _ = value;
        value = generator.newValue();
        return _;
      }
    });
  }
}

И, если вы разумно написали фейкер данных, мы можем теперь позвонить:

let myobj = new MyObject();
console.log(myobj.background); // some value
console.log(myobj.background); // some completely different value
console.log(myobj.background); // again some completely different value

Конечно, вам не нужен отдельный фейкер данных, но написание его как отдельной вещи означает, что ваш код останется незагроможденным и простым в обслуживании.

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