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!
javascript javascript-objects
add a comment |
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!
javascript javascript-objects
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
add a comment |
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!
javascript javascript-objects
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
javascript javascript-objects
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
add a comment |
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
add a comment |
5 Answers
5
active
oldest
votes
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);
}
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-Styleconst 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
|
show 2 more comments
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.
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
add a comment |
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.
If there'sclass
then you can add a getter withoutObject.defineProperty
– Andreas
Dec 31 '18 at 17:22
1
I disagree that using aclass
anddefineProperty
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
|
show 2 more comments
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>
add a comment |
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.
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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);
}
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-Styleconst 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
|
show 2 more comments
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);
}
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-Styleconst 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
|
show 2 more comments
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);
}
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);
}
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-Styleconst 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
|
show 2 more comments
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-Styleconst 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
|
show 2 more comments
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.
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
add a comment |
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.
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
add a comment |
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.
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.
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
add a comment |
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
add a comment |
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.
If there'sclass
then you can add a getter withoutObject.defineProperty
– Andreas
Dec 31 '18 at 17:22
1
I disagree that using aclass
anddefineProperty
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
|
show 2 more comments
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.
If there'sclass
then you can add a getter withoutObject.defineProperty
– Andreas
Dec 31 '18 at 17:22
1
I disagree that using aclass
anddefineProperty
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
|
show 2 more comments
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.
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.
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'sclass
then you can add a getter withoutObject.defineProperty
– Andreas
Dec 31 '18 at 17:22
1
I disagree that using aclass
anddefineProperty
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
|
show 2 more comments
If there'sclass
then you can add a getter withoutObject.defineProperty
– Andreas
Dec 31 '18 at 17:22
1
I disagree that using aclass
anddefineProperty
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
|
show 2 more comments
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>
add a comment |
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>
add a comment |
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>
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>
edited Jan 2 at 14:24
answered Jan 1 at 18:17
jaljal
648513
648513
add a comment |
add a comment |
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.
add a comment |
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.
add a comment |
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.
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.
answered Jan 8 at 12:14


Type-StyleType-Style
1,248827
1,248827
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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