Search code examples
javascriptjavascript-objects

Javascript: Get object with randomized property values


Generic Description

I am looking for a way to get an Object with a couple of defined properties and random values, that change whenever I access them. Also I want to overwrite the properties dynamically and find a way to get a new Object.

Checklist of things I want to accomplish

  • Object has randomized property values
  • "new instance" or new Object can be created with new values
  • Dynamically replacing the Object is possible and the two above criteria are still valid

Code based detailed explanation

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

By doing this I baseObj is a reference to an object that stays the same.

In other words, no matter how often you use the baseObj or how often you access its properties the values will not change, since Math.random() is executed and the value is assigned to the objects property.

To overcome this issue I wrapped the output into a function that I can call it, and get a new Object with new values:

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

So far so good, but now let's say I have this function expects an object but if it is not there I'll use baseObj as default.

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

The point where I am struggling right now is how to overwrite the "baseObj function pattern" with the template of whatever tempObj is?

The expected result when calling draw() again without any parameters is that you get a big border of at least 20 and a random background color. Basically updating baseObj with new rules on what it's return object should be.

Demo Link / Snippet

I have a codepen link here where I do a little bit more and merge the tempObj with the baseObj but I am still looking for a solution to the same problem. 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> 

Questions / Misc.

Is there a better way to get fresh values that putting it into a function? Feel free to edit the question if you think it makes it easier to understand.

Happy new Year!


Solution

  • I figured out my missunderstanding and misconception about the enhancement and randomness of the properties.

    By providing the object literal as parameter to a function (calculate):

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

    The border property is already processed and there is no way of figuring out what the calculation behind the value is.

    Possible solutions, whould be actually passing a factory to the calculate function, so that you can get multiple object with the same calculations.

    Or thanks to @cgTag and @Bergi and Mike 'Pomax' Kamermans, there is plenty of ways around that.