Javascript: Get object with randomized property values












1















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!










share|improve this question




















  • 1





    tempObj = baseObj();. Is that all you're trying to do?

    – Patrick Roberts
    Dec 31 '18 at 17:18











  • Can't you just use a getter? developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

    – cgTag
    Dec 31 '18 at 17:22











  • Can you explain exactly what is not working in your demo? By the way you could also use the code snippets here for your demo.

    – jal
    Dec 31 '18 at 17:45











  • @PatrickRoberts not exactly I want to store obj in a way so that I can call baseObj again and get a new obj with updated values.

    – Type-Style
    Jan 1 at 17:01











  • @jal_a yea sure I'll update the question and add a snippet. What is not working in the demo is, that once pressing the second button the first one does nothing. I added a little text there too. In that case I want the bigger border and random color.

    – Type-Style
    Jan 1 at 17:02
















1















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!










share|improve this question




















  • 1





    tempObj = baseObj();. Is that all you're trying to do?

    – Patrick Roberts
    Dec 31 '18 at 17:18











  • Can't you just use a getter? developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

    – cgTag
    Dec 31 '18 at 17:22











  • Can you explain exactly what is not working in your demo? By the way you could also use the code snippets here for your demo.

    – jal
    Dec 31 '18 at 17:45











  • @PatrickRoberts not exactly I want to store obj in a way so that I can call baseObj again and get a new obj with updated values.

    – Type-Style
    Jan 1 at 17:01











  • @jal_a yea sure I'll update the question and add a snippet. What is not working in the demo is, that once pressing the second button the first one does nothing. I added a little text there too. In that case I want the bigger border and random color.

    – Type-Style
    Jan 1 at 17:02














1












1








1








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!










share|improve this question
















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!






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>





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>






javascript javascript-objects






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 1 at 17:38







Type-Style

















asked Dec 31 '18 at 17:10









Type-StyleType-Style

1,248827




1,248827








  • 1





    tempObj = baseObj();. Is that all you're trying to do?

    – Patrick Roberts
    Dec 31 '18 at 17:18











  • Can't you just use a getter? developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

    – cgTag
    Dec 31 '18 at 17:22











  • Can you explain exactly what is not working in your demo? By the way you could also use the code snippets here for your demo.

    – jal
    Dec 31 '18 at 17:45











  • @PatrickRoberts not exactly I want to store obj in a way so that I can call baseObj again and get a new obj with updated values.

    – Type-Style
    Jan 1 at 17:01











  • @jal_a yea sure I'll update the question and add a snippet. What is not working in the demo is, that once pressing the second button the first one does nothing. I added a little text there too. In that case I want the bigger border and random color.

    – Type-Style
    Jan 1 at 17:02














  • 1





    tempObj = baseObj();. Is that all you're trying to do?

    – Patrick Roberts
    Dec 31 '18 at 17:18











  • Can't you just use a getter? developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

    – cgTag
    Dec 31 '18 at 17:22











  • Can you explain exactly what is not working in your demo? By the way you could also use the code snippets here for your demo.

    – jal
    Dec 31 '18 at 17:45











  • @PatrickRoberts not exactly I want to store obj in a way so that I can call baseObj again and get a new obj with updated values.

    – Type-Style
    Jan 1 at 17:01











  • @jal_a yea sure I'll update the question and add a snippet. What is not working in the demo is, that once pressing the second button the first one does nothing. I added a little text there too. In that case I want the bigger border and random color.

    – Type-Style
    Jan 1 at 17:02








1




1





tempObj = baseObj();. Is that all you're trying to do?

– Patrick Roberts
Dec 31 '18 at 17:18





tempObj = baseObj();. Is that all you're trying to do?

– Patrick Roberts
Dec 31 '18 at 17:18













Can't you just use a getter? developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

– cgTag
Dec 31 '18 at 17:22





Can't you just use a getter? developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

– cgTag
Dec 31 '18 at 17:22













Can you explain exactly what is not working in your demo? By the way you could also use the code snippets here for your demo.

– jal
Dec 31 '18 at 17:45





Can you explain exactly what is not working in your demo? By the way you could also use the code snippets here for your demo.

– jal
Dec 31 '18 at 17:45













@PatrickRoberts not exactly I want to store obj in a way so that I can call baseObj again and get a new obj with updated values.

– Type-Style
Jan 1 at 17:01





@PatrickRoberts not exactly I want to store obj in a way so that I can call baseObj again and get a new obj with updated values.

– Type-Style
Jan 1 at 17:01













@jal_a yea sure I'll update the question and add a snippet. What is not working in the demo is, that once pressing the second button the first one does nothing. I added a little text there too. In that case I want the bigger border and random color.

– Type-Style
Jan 1 at 17:02





@jal_a yea sure I'll update the question and add a snippet. What is not working in the demo is, that once pressing the second button the first one does nothing. I added a little text there too. In that case I want the bigger border and random color.

– Type-Style
Jan 1 at 17:02












5 Answers
5






active

oldest

votes


















2















Is there a better way to get fresh values than putting it into a function?




No, a function to produce new values (called "factory") is the simplest way.




The point where I am struggling right now is how to use the template for whatever tempObj is?




You just have to call the function:



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


Btw, since you're using ES6 you might want to make use of default parameter syntax:



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





I want to update with new rules on what it's return object should be.




Just store the update, not the whole tempObj (including the random additions) for the enhancement.



let enhancement = {};
function calculate(overwrite) {
enhancement = {...enhancement, ...overwrite}; // do not merge the randomObj() here!
const tempObj = {
...randomObj(),
...enhancement
};
draw(tempObj);
}





share|improve this answer


























  • First of, the default parameter is an excellent idea. Thanks. But what is missing from your answer is how do I create a new function that gives me random properties of tempObj after everything is merged.

    – Type-Style
    Jan 1 at 17:10











  • @Type-Style const randomObj = () => (…); is the function. It is the same as in your question and the first snippet in my answer.

    – Bergi
    Jan 1 at 17:14











  • I see, but I think we are misunderstanding each-other a little bit. Let me try to be a little more concrete. Let's say you call draw with an obj so that randomObj does not need to be called. But inside of draw you want to make sure that next time some calls draw it uses the configuration of whatever you called it with. Please see the updated demo/snippet with the added paragraph text. I hope that provides a clearer view of the issue.

    – Type-Style
    Jan 1 at 17:29













  • So you actually don't want to get a new object? That's a totally new question.

    – Bergi
    Jan 1 at 18:08











  • I want a object or to be more precise I want update/replace randomObj with the merged object. This is the issue from the beginning, sorry If I did not find a good way of expression the issue in a clearer way.

    – Type-Style
    Jan 1 at 18:14



















1














I have to admit that I don't really understand this question, but given the other answers I thought I would add a different opinion and this seems like an opinion question.



You can define an object that uses getter methods that generates random property values.



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.


The above gives you randomized property values, but they are random everytime they are read. You can freeze the values by cloning the object.



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


You can now mix together different objects to select which values you want as random.



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


Now, I'm guessing this is kind of what you wanted.






share|improve this answer


























  • Well thanks for your anser [at]cqTag / @Bergi.I have not thought about using functions as properties in that case. What I was trying to do was kinda the opposite and use plain properties that are not functions and want to dynamically wrap the object they are in a function so that they become random again.

    – Type-Style
    Jan 1 at 17:07



















0














Nothing too complicated here: create an object or use a class, and then instead of setting properties "the normal way", use defineProperty to set up a get function for any property you want to randomize.



So let's use a class, because it's much easier to maintain:





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


And assuming you wrote your data faker sensibly, we can now call:



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


Of course you don't need a separate data faker, but writing one as a separate thing means your code's going to stay uncluttered, and easy to maintain.






share|improve this answer


























  • If there's class then you can add a getter without Object.defineProperty

    – Andreas
    Dec 31 '18 at 17:22






  • 1





    I disagree that using a class and defineProperty are "Nothing too complicated here". Especially you don't need the class at all, it would be much simpler and easier to maintain if you had a factory function that took an array of property names.

    – Bergi
    Dec 31 '18 at 17:23











  • writing a getter, however, means we need to pollute the class itself with the values we're randomizing. Using a defineProperty means we can hide that in a closure so that external code can't get to it

    – Mike 'Pomax' Kamermans
    Dec 31 '18 at 17:24








  • 1





    @Andreas Only if you knew how many properties there should be beforehand

    – Bergi
    Dec 31 '18 at 17:24











  • @Bergi sure, but you realise that you just wrote a comment that should have been an answer, right? Of course you can use a datafaker with an array (heck, why even use the array, just plug your datafaker straight into whatever code actually needs it) but this answer sticks with the idea of having an object. If you want to take it further and reduce that to an array with a faker, then we both know that should be a separate answer, not a comment.

    – Mike 'Pomax' Kamermans
    Dec 31 '18 at 17:28



















0














I think the simplest way is to use methods on the object and overwrite them by the new object. This gives you dynamic values and works around the overhead of redefining getters. The only thing to note is that you have to invoke the methods instead of reading the properties i.e. baseObj.border() instead of 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>








share|improve this answer

































    -1














    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.






    share|improve this answer























      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53989815%2fjavascript-get-object-with-randomized-property-values%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      5 Answers
      5






      active

      oldest

      votes








      5 Answers
      5






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      2















      Is there a better way to get fresh values than putting it into a function?




      No, a function to produce new values (called "factory") is the simplest way.




      The point where I am struggling right now is how to use the template for whatever tempObj is?




      You just have to call the function:



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


      Btw, since you're using ES6 you might want to make use of default parameter syntax:



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





      I want to update with new rules on what it's return object should be.




      Just store the update, not the whole tempObj (including the random additions) for the enhancement.



      let enhancement = {};
      function calculate(overwrite) {
      enhancement = {...enhancement, ...overwrite}; // do not merge the randomObj() here!
      const tempObj = {
      ...randomObj(),
      ...enhancement
      };
      draw(tempObj);
      }





      share|improve this answer


























      • First of, the default parameter is an excellent idea. Thanks. But what is missing from your answer is how do I create a new function that gives me random properties of tempObj after everything is merged.

        – Type-Style
        Jan 1 at 17:10











      • @Type-Style const randomObj = () => (…); is the function. It is the same as in your question and the first snippet in my answer.

        – Bergi
        Jan 1 at 17:14











      • I see, but I think we are misunderstanding each-other a little bit. Let me try to be a little more concrete. Let's say you call draw with an obj so that randomObj does not need to be called. But inside of draw you want to make sure that next time some calls draw it uses the configuration of whatever you called it with. Please see the updated demo/snippet with the added paragraph text. I hope that provides a clearer view of the issue.

        – Type-Style
        Jan 1 at 17:29













      • So you actually don't want to get a new object? That's a totally new question.

        – Bergi
        Jan 1 at 18:08











      • I want a object or to be more precise I want update/replace randomObj with the merged object. This is the issue from the beginning, sorry If I did not find a good way of expression the issue in a clearer way.

        – Type-Style
        Jan 1 at 18:14
















      2















      Is there a better way to get fresh values than putting it into a function?




      No, a function to produce new values (called "factory") is the simplest way.




      The point where I am struggling right now is how to use the template for whatever tempObj is?




      You just have to call the function:



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


      Btw, since you're using ES6 you might want to make use of default parameter syntax:



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





      I want to update with new rules on what it's return object should be.




      Just store the update, not the whole tempObj (including the random additions) for the enhancement.



      let enhancement = {};
      function calculate(overwrite) {
      enhancement = {...enhancement, ...overwrite}; // do not merge the randomObj() here!
      const tempObj = {
      ...randomObj(),
      ...enhancement
      };
      draw(tempObj);
      }





      share|improve this answer


























      • First of, the default parameter is an excellent idea. Thanks. But what is missing from your answer is how do I create a new function that gives me random properties of tempObj after everything is merged.

        – Type-Style
        Jan 1 at 17:10











      • @Type-Style const randomObj = () => (…); is the function. It is the same as in your question and the first snippet in my answer.

        – Bergi
        Jan 1 at 17:14











      • I see, but I think we are misunderstanding each-other a little bit. Let me try to be a little more concrete. Let's say you call draw with an obj so that randomObj does not need to be called. But inside of draw you want to make sure that next time some calls draw it uses the configuration of whatever you called it with. Please see the updated demo/snippet with the added paragraph text. I hope that provides a clearer view of the issue.

        – Type-Style
        Jan 1 at 17:29













      • So you actually don't want to get a new object? That's a totally new question.

        – Bergi
        Jan 1 at 18:08











      • I want a object or to be more precise I want update/replace randomObj with the merged object. This is the issue from the beginning, sorry If I did not find a good way of expression the issue in a clearer way.

        – Type-Style
        Jan 1 at 18:14














      2












      2








      2








      Is there a better way to get fresh values than putting it into a function?




      No, a function to produce new values (called "factory") is the simplest way.




      The point where I am struggling right now is how to use the template for whatever tempObj is?




      You just have to call the function:



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


      Btw, since you're using ES6 you might want to make use of default parameter syntax:



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





      I want to update with new rules on what it's return object should be.




      Just store the update, not the whole tempObj (including the random additions) for the enhancement.



      let enhancement = {};
      function calculate(overwrite) {
      enhancement = {...enhancement, ...overwrite}; // do not merge the randomObj() here!
      const tempObj = {
      ...randomObj(),
      ...enhancement
      };
      draw(tempObj);
      }





      share|improve this answer
















      Is there a better way to get fresh values than putting it into a function?




      No, a function to produce new values (called "factory") is the simplest way.




      The point where I am struggling right now is how to use the template for whatever tempObj is?




      You just have to call the function:



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


      Btw, since you're using ES6 you might want to make use of default parameter syntax:



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





      I want to update with new rules on what it's return object should be.




      Just store the update, not the whole tempObj (including the random additions) for the enhancement.



      let enhancement = {};
      function calculate(overwrite) {
      enhancement = {...enhancement, ...overwrite}; // do not merge the randomObj() here!
      const tempObj = {
      ...randomObj(),
      ...enhancement
      };
      draw(tempObj);
      }






      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Jan 1 at 18:13

























      answered Dec 31 '18 at 17:33









      BergiBergi

      379k63577910




      379k63577910













      • First of, the default parameter is an excellent idea. Thanks. But what is missing from your answer is how do I create a new function that gives me random properties of tempObj after everything is merged.

        – Type-Style
        Jan 1 at 17:10











      • @Type-Style const randomObj = () => (…); is the function. It is the same as in your question and the first snippet in my answer.

        – Bergi
        Jan 1 at 17:14











      • I see, but I think we are misunderstanding each-other a little bit. Let me try to be a little more concrete. Let's say you call draw with an obj so that randomObj does not need to be called. But inside of draw you want to make sure that next time some calls draw it uses the configuration of whatever you called it with. Please see the updated demo/snippet with the added paragraph text. I hope that provides a clearer view of the issue.

        – Type-Style
        Jan 1 at 17:29













      • So you actually don't want to get a new object? That's a totally new question.

        – Bergi
        Jan 1 at 18:08











      • I want a object or to be more precise I want update/replace randomObj with the merged object. This is the issue from the beginning, sorry If I did not find a good way of expression the issue in a clearer way.

        – Type-Style
        Jan 1 at 18:14



















      • First of, the default parameter is an excellent idea. Thanks. But what is missing from your answer is how do I create a new function that gives me random properties of tempObj after everything is merged.

        – Type-Style
        Jan 1 at 17:10











      • @Type-Style const randomObj = () => (…); is the function. It is the same as in your question and the first snippet in my answer.

        – Bergi
        Jan 1 at 17:14











      • I see, but I think we are misunderstanding each-other a little bit. Let me try to be a little more concrete. Let's say you call draw with an obj so that randomObj does not need to be called. But inside of draw you want to make sure that next time some calls draw it uses the configuration of whatever you called it with. Please see the updated demo/snippet with the added paragraph text. I hope that provides a clearer view of the issue.

        – Type-Style
        Jan 1 at 17:29













      • So you actually don't want to get a new object? That's a totally new question.

        – Bergi
        Jan 1 at 18:08











      • I want a object or to be more precise I want update/replace randomObj with the merged object. This is the issue from the beginning, sorry If I did not find a good way of expression the issue in a clearer way.

        – Type-Style
        Jan 1 at 18:14

















      First of, the default parameter is an excellent idea. Thanks. But what is missing from your answer is how do I create a new function that gives me random properties of tempObj after everything is merged.

      – Type-Style
      Jan 1 at 17:10





      First of, the default parameter is an excellent idea. Thanks. But what is missing from your answer is how do I create a new function that gives me random properties of tempObj after everything is merged.

      – Type-Style
      Jan 1 at 17:10













      @Type-Style const randomObj = () => (…); is the function. It is the same as in your question and the first snippet in my answer.

      – Bergi
      Jan 1 at 17:14





      @Type-Style const randomObj = () => (…); is the function. It is the same as in your question and the first snippet in my answer.

      – Bergi
      Jan 1 at 17:14













      I see, but I think we are misunderstanding each-other a little bit. Let me try to be a little more concrete. Let's say you call draw with an obj so that randomObj does not need to be called. But inside of draw you want to make sure that next time some calls draw it uses the configuration of whatever you called it with. Please see the updated demo/snippet with the added paragraph text. I hope that provides a clearer view of the issue.

      – Type-Style
      Jan 1 at 17:29







      I see, but I think we are misunderstanding each-other a little bit. Let me try to be a little more concrete. Let's say you call draw with an obj so that randomObj does not need to be called. But inside of draw you want to make sure that next time some calls draw it uses the configuration of whatever you called it with. Please see the updated demo/snippet with the added paragraph text. I hope that provides a clearer view of the issue.

      – Type-Style
      Jan 1 at 17:29















      So you actually don't want to get a new object? That's a totally new question.

      – Bergi
      Jan 1 at 18:08





      So you actually don't want to get a new object? That's a totally new question.

      – Bergi
      Jan 1 at 18:08













      I want a object or to be more precise I want update/replace randomObj with the merged object. This is the issue from the beginning, sorry If I did not find a good way of expression the issue in a clearer way.

      – Type-Style
      Jan 1 at 18:14





      I want a object or to be more precise I want update/replace randomObj with the merged object. This is the issue from the beginning, sorry If I did not find a good way of expression the issue in a clearer way.

      – Type-Style
      Jan 1 at 18:14













      1














      I have to admit that I don't really understand this question, but given the other answers I thought I would add a different opinion and this seems like an opinion question.



      You can define an object that uses getter methods that generates random property values.



      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.


      The above gives you randomized property values, but they are random everytime they are read. You can freeze the values by cloning the object.



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


      You can now mix together different objects to select which values you want as random.



      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


      Now, I'm guessing this is kind of what you wanted.






      share|improve this answer


























      • Well thanks for your anser [at]cqTag / @Bergi.I have not thought about using functions as properties in that case. What I was trying to do was kinda the opposite and use plain properties that are not functions and want to dynamically wrap the object they are in a function so that they become random again.

        – Type-Style
        Jan 1 at 17:07
















      1














      I have to admit that I don't really understand this question, but given the other answers I thought I would add a different opinion and this seems like an opinion question.



      You can define an object that uses getter methods that generates random property values.



      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.


      The above gives you randomized property values, but they are random everytime they are read. You can freeze the values by cloning the object.



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


      You can now mix together different objects to select which values you want as random.



      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


      Now, I'm guessing this is kind of what you wanted.






      share|improve this answer


























      • Well thanks for your anser [at]cqTag / @Bergi.I have not thought about using functions as properties in that case. What I was trying to do was kinda the opposite and use plain properties that are not functions and want to dynamically wrap the object they are in a function so that they become random again.

        – Type-Style
        Jan 1 at 17:07














      1












      1








      1







      I have to admit that I don't really understand this question, but given the other answers I thought I would add a different opinion and this seems like an opinion question.



      You can define an object that uses getter methods that generates random property values.



      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.


      The above gives you randomized property values, but they are random everytime they are read. You can freeze the values by cloning the object.



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


      You can now mix together different objects to select which values you want as random.



      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


      Now, I'm guessing this is kind of what you wanted.






      share|improve this answer















      I have to admit that I don't really understand this question, but given the other answers I thought I would add a different opinion and this seems like an opinion question.



      You can define an object that uses getter methods that generates random property values.



      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.


      The above gives you randomized property values, but they are random everytime they are read. You can freeze the values by cloning the object.



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


      You can now mix together different objects to select which values you want as random.



      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


      Now, I'm guessing this is kind of what you wanted.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Dec 31 '18 at 17:50









      Bergi

      379k63577910




      379k63577910










      answered Dec 31 '18 at 17:44









      cgTagcgTag

      24.3k864114




      24.3k864114













      • Well thanks for your anser [at]cqTag / @Bergi.I have not thought about using functions as properties in that case. What I was trying to do was kinda the opposite and use plain properties that are not functions and want to dynamically wrap the object they are in a function so that they become random again.

        – Type-Style
        Jan 1 at 17:07



















      • Well thanks for your anser [at]cqTag / @Bergi.I have not thought about using functions as properties in that case. What I was trying to do was kinda the opposite and use plain properties that are not functions and want to dynamically wrap the object they are in a function so that they become random again.

        – Type-Style
        Jan 1 at 17:07

















      Well thanks for your anser [at]cqTag / @Bergi.I have not thought about using functions as properties in that case. What I was trying to do was kinda the opposite and use plain properties that are not functions and want to dynamically wrap the object they are in a function so that they become random again.

      – Type-Style
      Jan 1 at 17:07





      Well thanks for your anser [at]cqTag / @Bergi.I have not thought about using functions as properties in that case. What I was trying to do was kinda the opposite and use plain properties that are not functions and want to dynamically wrap the object they are in a function so that they become random again.

      – Type-Style
      Jan 1 at 17:07











      0














      Nothing too complicated here: create an object or use a class, and then instead of setting properties "the normal way", use defineProperty to set up a get function for any property you want to randomize.



      So let's use a class, because it's much easier to maintain:





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


      And assuming you wrote your data faker sensibly, we can now call:



      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


      Of course you don't need a separate data faker, but writing one as a separate thing means your code's going to stay uncluttered, and easy to maintain.






      share|improve this answer


























      • If there's class then you can add a getter without Object.defineProperty

        – Andreas
        Dec 31 '18 at 17:22






      • 1





        I disagree that using a class and defineProperty are "Nothing too complicated here". Especially you don't need the class at all, it would be much simpler and easier to maintain if you had a factory function that took an array of property names.

        – Bergi
        Dec 31 '18 at 17:23











      • writing a getter, however, means we need to pollute the class itself with the values we're randomizing. Using a defineProperty means we can hide that in a closure so that external code can't get to it

        – Mike 'Pomax' Kamermans
        Dec 31 '18 at 17:24








      • 1





        @Andreas Only if you knew how many properties there should be beforehand

        – Bergi
        Dec 31 '18 at 17:24











      • @Bergi sure, but you realise that you just wrote a comment that should have been an answer, right? Of course you can use a datafaker with an array (heck, why even use the array, just plug your datafaker straight into whatever code actually needs it) but this answer sticks with the idea of having an object. If you want to take it further and reduce that to an array with a faker, then we both know that should be a separate answer, not a comment.

        – Mike 'Pomax' Kamermans
        Dec 31 '18 at 17:28
















      0














      Nothing too complicated here: create an object or use a class, and then instead of setting properties "the normal way", use defineProperty to set up a get function for any property you want to randomize.



      So let's use a class, because it's much easier to maintain:





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


      And assuming you wrote your data faker sensibly, we can now call:



      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


      Of course you don't need a separate data faker, but writing one as a separate thing means your code's going to stay uncluttered, and easy to maintain.






      share|improve this answer


























      • If there's class then you can add a getter without Object.defineProperty

        – Andreas
        Dec 31 '18 at 17:22






      • 1





        I disagree that using a class and defineProperty are "Nothing too complicated here". Especially you don't need the class at all, it would be much simpler and easier to maintain if you had a factory function that took an array of property names.

        – Bergi
        Dec 31 '18 at 17:23











      • writing a getter, however, means we need to pollute the class itself with the values we're randomizing. Using a defineProperty means we can hide that in a closure so that external code can't get to it

        – Mike 'Pomax' Kamermans
        Dec 31 '18 at 17:24








      • 1





        @Andreas Only if you knew how many properties there should be beforehand

        – Bergi
        Dec 31 '18 at 17:24











      • @Bergi sure, but you realise that you just wrote a comment that should have been an answer, right? Of course you can use a datafaker with an array (heck, why even use the array, just plug your datafaker straight into whatever code actually needs it) but this answer sticks with the idea of having an object. If you want to take it further and reduce that to an array with a faker, then we both know that should be a separate answer, not a comment.

        – Mike 'Pomax' Kamermans
        Dec 31 '18 at 17:28














      0












      0








      0







      Nothing too complicated here: create an object or use a class, and then instead of setting properties "the normal way", use defineProperty to set up a get function for any property you want to randomize.



      So let's use a class, because it's much easier to maintain:





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


      And assuming you wrote your data faker sensibly, we can now call:



      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


      Of course you don't need a separate data faker, but writing one as a separate thing means your code's going to stay uncluttered, and easy to maintain.






      share|improve this answer















      Nothing too complicated here: create an object or use a class, and then instead of setting properties "the normal way", use defineProperty to set up a get function for any property you want to randomize.



      So let's use a class, because it's much easier to maintain:





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


      And assuming you wrote your data faker sensibly, we can now call:



      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


      Of course you don't need a separate data faker, but writing one as a separate thing means your code's going to stay uncluttered, and easy to maintain.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Dec 31 '18 at 17:23

























      answered Dec 31 '18 at 17:21









      Mike 'Pomax' KamermansMike 'Pomax' Kamermans

      28.4k759100




      28.4k759100













      • If there's class then you can add a getter without Object.defineProperty

        – Andreas
        Dec 31 '18 at 17:22






      • 1





        I disagree that using a class and defineProperty are "Nothing too complicated here". Especially you don't need the class at all, it would be much simpler and easier to maintain if you had a factory function that took an array of property names.

        – Bergi
        Dec 31 '18 at 17:23











      • writing a getter, however, means we need to pollute the class itself with the values we're randomizing. Using a defineProperty means we can hide that in a closure so that external code can't get to it

        – Mike 'Pomax' Kamermans
        Dec 31 '18 at 17:24








      • 1





        @Andreas Only if you knew how many properties there should be beforehand

        – Bergi
        Dec 31 '18 at 17:24











      • @Bergi sure, but you realise that you just wrote a comment that should have been an answer, right? Of course you can use a datafaker with an array (heck, why even use the array, just plug your datafaker straight into whatever code actually needs it) but this answer sticks with the idea of having an object. If you want to take it further and reduce that to an array with a faker, then we both know that should be a separate answer, not a comment.

        – Mike 'Pomax' Kamermans
        Dec 31 '18 at 17:28



















      • If there's class then you can add a getter without Object.defineProperty

        – Andreas
        Dec 31 '18 at 17:22






      • 1





        I disagree that using a class and defineProperty are "Nothing too complicated here". Especially you don't need the class at all, it would be much simpler and easier to maintain if you had a factory function that took an array of property names.

        – Bergi
        Dec 31 '18 at 17:23











      • writing a getter, however, means we need to pollute the class itself with the values we're randomizing. Using a defineProperty means we can hide that in a closure so that external code can't get to it

        – Mike 'Pomax' Kamermans
        Dec 31 '18 at 17:24








      • 1





        @Andreas Only if you knew how many properties there should be beforehand

        – Bergi
        Dec 31 '18 at 17:24











      • @Bergi sure, but you realise that you just wrote a comment that should have been an answer, right? Of course you can use a datafaker with an array (heck, why even use the array, just plug your datafaker straight into whatever code actually needs it) but this answer sticks with the idea of having an object. If you want to take it further and reduce that to an array with a faker, then we both know that should be a separate answer, not a comment.

        – Mike 'Pomax' Kamermans
        Dec 31 '18 at 17:28

















      If there's class then you can add a getter without Object.defineProperty

      – Andreas
      Dec 31 '18 at 17:22





      If there's class then you can add a getter without Object.defineProperty

      – Andreas
      Dec 31 '18 at 17:22




      1




      1





      I disagree that using a class and defineProperty are "Nothing too complicated here". Especially you don't need the class at all, it would be much simpler and easier to maintain if you had a factory function that took an array of property names.

      – Bergi
      Dec 31 '18 at 17:23





      I disagree that using a class and defineProperty are "Nothing too complicated here". Especially you don't need the class at all, it would be much simpler and easier to maintain if you had a factory function that took an array of property names.

      – Bergi
      Dec 31 '18 at 17:23













      writing a getter, however, means we need to pollute the class itself with the values we're randomizing. Using a defineProperty means we can hide that in a closure so that external code can't get to it

      – Mike 'Pomax' Kamermans
      Dec 31 '18 at 17:24







      writing a getter, however, means we need to pollute the class itself with the values we're randomizing. Using a defineProperty means we can hide that in a closure so that external code can't get to it

      – Mike 'Pomax' Kamermans
      Dec 31 '18 at 17:24






      1




      1





      @Andreas Only if you knew how many properties there should be beforehand

      – Bergi
      Dec 31 '18 at 17:24





      @Andreas Only if you knew how many properties there should be beforehand

      – Bergi
      Dec 31 '18 at 17:24













      @Bergi sure, but you realise that you just wrote a comment that should have been an answer, right? Of course you can use a datafaker with an array (heck, why even use the array, just plug your datafaker straight into whatever code actually needs it) but this answer sticks with the idea of having an object. If you want to take it further and reduce that to an array with a faker, then we both know that should be a separate answer, not a comment.

      – Mike 'Pomax' Kamermans
      Dec 31 '18 at 17:28





      @Bergi sure, but you realise that you just wrote a comment that should have been an answer, right? Of course you can use a datafaker with an array (heck, why even use the array, just plug your datafaker straight into whatever code actually needs it) but this answer sticks with the idea of having an object. If you want to take it further and reduce that to an array with a faker, then we both know that should be a separate answer, not a comment.

      – Mike 'Pomax' Kamermans
      Dec 31 '18 at 17:28











      0














      I think the simplest way is to use methods on the object and overwrite them by the new object. This gives you dynamic values and works around the overhead of redefining getters. The only thing to note is that you have to invoke the methods instead of reading the properties i.e. baseObj.border() instead of 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>








      share|improve this answer






























        0














        I think the simplest way is to use methods on the object and overwrite them by the new object. This gives you dynamic values and works around the overhead of redefining getters. The only thing to note is that you have to invoke the methods instead of reading the properties i.e. baseObj.border() instead of 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>








        share|improve this answer




























          0












          0








          0







          I think the simplest way is to use methods on the object and overwrite them by the new object. This gives you dynamic values and works around the overhead of redefining getters. The only thing to note is that you have to invoke the methods instead of reading the properties i.e. baseObj.border() instead of 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>








          share|improve this answer















          I think the simplest way is to use methods on the object and overwrite them by the new object. This gives you dynamic values and works around the overhead of redefining getters. The only thing to note is that you have to invoke the methods instead of reading the properties i.e. baseObj.border() instead of 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>








          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>





          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>






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Jan 2 at 14:24

























          answered Jan 1 at 18:17









          jaljal

          648513




          648513























              -1














              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.






              share|improve this answer




























                -1














                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.






                share|improve this answer


























                  -1












                  -1








                  -1







                  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.






                  share|improve this answer













                  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.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Jan 8 at 12:14









                  Type-StyleType-Style

                  1,248827




                  1,248827






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53989815%2fjavascript-get-object-with-randomized-property-values%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      MongoDB - Not Authorized To Execute Command

                      in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith

                      How to fix TextFormField cause rebuild widget in Flutter