我正在寻找一种方法,以获取具有几个定义的属性和随机值的对象,每次访问它们时它们都会改变。另外,我想动态地覆盖属性,并找到获取新对象的方法。
var baseObj = {
border: Math.round(Math.random() * 10 +3),
background: 'hsl('+Math.random() * 360 + 'deg 100% 50%)'
}
通过此操作,baseObj是对保持不变的对象的引用。
换句话说,由于您执行了 Math.random()并且已将值分配给了对象,因此无论您使用baseObj的频率或其访问属性的频率都不会改变。对象属性。
要克服这个问题,我将输出包装到一个可以调用的函数中,并获得了一个具有新值的新Object:
var baseObj = () => ({
border: Math.round(Math.random() * 10 +3),
background: 'hsl('+Math.random() * 360 + 'deg 100% 50%)'
})
到目前为止,还不错,但是现在让我们说这个函数需要一个对象,但是如果没有,我将使用baseObj作为默认对象。
draw = tempObj => {
if (!tempObj) {tempObj = baseObj;}
div.style.borderWidth = tempObj.border + "px";
div.style.backgroundColor = tempObj.background;
// missing here merge the two objects
// missing and main question how to update baseObj with new information
}
draw({
border: Math.round(Math.random() * 55 + 20)
})
我现在正在努力解决的问题是如何用任何tempObj模板覆盖“ baseObj函数模式” ?
再次预期结果,不带任何参数再次调用draw()时,您将获得至少20的大边框和随机的 背景颜色。基本上用关于什么的新规则更新baseObj 它应该是返回对象。
我在这里有一个Codepen链接,在这里我可以做更多的工作,并将tempObj与baseObj合并,但是我仍在寻找解决同一问题的方法。 https://codepen.io/Type-Style/pen/VqMMJd?editors=0010
var div = document.querySelector("#div"),
getNewStyle = document.querySelector("#getNewStyle"),
changeStyle1 = document.querySelector("#changeStyle1"),
baseObj = () => ({
border: Math.round(Math.random() * 10 +3),
background: 'hsl('+Math.random() * 360 + 'deg 100% 50%)'
}),
enhancementObj = null,
getObj = () => (enhancementObj || baseObj()),
calculate = (overwriteObj) => {
if (!overwriteObj) {
var tempObj = getObj();
} else {
var tempObj = { // merge the two objects
...getObj(),
...overwriteObj
}
enhancementObj = tempObj; // now I have static values again :-(
}
draw(tempObj);
},
draw = tempObj => {
div.style.borderWidth = tempObj.border + "px";
div.style.backgroundColor = tempObj.background;
}
getNewStyle.onclick = () => {draw(getObj())};
changeStyle1.onclick = () => {calculate({
border: Math.round(Math.random() * 55 + 20)
})};
#div {
width: 300px;
height: 300px;
box-sizing: border-box;
border-style: dashed;
border-radius: 50%;
}
/* excuse me using IDs and useless Names in CSS, I know better but this is a JS Question */
<div id="div"></div>
<button id="getNewStyle">getNewStyle</button>
<br>
<button id="changeStyle1">changeStyle1</button>
<p>Press the first button to get random border-size and background color.
The second button should overite the border-size and clicking the first button again should give you a bigger border and random background color, but it doesn't.</p>
是否有更好的方法来获取将其放入函数的新值? 如果您认为问题更容易理解,请随时进行编辑。
新年快乐!
答案 0 :(得分:2)
有比获取新值更好的方法吗?
不,产生新值的函数(称为“工厂”)是最简单的方法。
我现在正在努力的问题是如何将模板用于任何tempObj?
您只需要调用函数:
const randomObj = () => ({
border: Math.round(Math.random() * 10 +3),
background: 'hsl('+Math.random() * 360 + 'deg 100% 50%)'
});
function draw(tempObj) {
if (!tempObj) tempObj = randomObj();
// ^^
div.style.borderWidth = tempObj.border + "px";
div.style.backgroundColor = tempObj.background;
}
顺便说一句,由于您使用的是ES6,因此您可能希望使用默认参数语法:
function draw(tempObj = randomObj()) {
div.style.borderWidth = tempObj.border + "px";
div.style.backgroundColor = tempObj.background;
}
我想用新规则更新返回对象的内容。
只需存储更新,而不存储整个增强功能的tempObj
(包括随机添加的内容)。
let enhancement = {};
function calculate(overwrite) {
enhancement = {...enhancement, ...overwrite}; // do not merge the randomObj() here!
const tempObj = {
...randomObj(),
...enhancement
};
draw(tempObj);
}
答案 1 :(得分:1)
我不得不承认我不太了解这个问题,但是鉴于其他答案,我认为我会添加一个不同的 opinion ,这似乎是一个 opinion 问题。
您可以定义一个使用使用getter方法生成随机属性值的对象。
var baseObj = {
get border() { return Math.round(Math.random() * 10 +3); },
get background() { return 'hsl('+Math.random() * 360 + 'deg 100% 50%)'; }
};
console.log(baseObj.border); // prints a random value
console.log(baseObj.border); // prints a different value each time.
以上提供了随机属性值,但是每次读取它们都是随机的。您可以通过克隆对象来冻结值。
var frozenObj = Object.assign({}, baseObj); // or {...baseObj}
console.log(frozenObj.border); // prints a value
console.log(frozenObj.border); // prints the same value
您现在可以将不同的对象混合在一起,以选择要随机选择的值。
var example = Object.assign({}, baseObj, {border:999}); // or {...baseObj, border:999}
console.log(example.border); // prints 999
console.log(example.background); // prints a random value, but the same on each call
现在,我正在猜测,这正是您想要的。
答案 2 :(得分:0)
这里没有什么太复杂的:创建对象或使用类,然后使用“ defineProperty”为要设置的任何属性设置“ get
”功能,而不是“常规方式”设置属性。随机化。
因此,我们使用一个类,因为它更易于维护:
import { StringGenerator } from './generators.js';
class MyObj {
constructor() {
this.createRandomProperty('background', StringGenerator);
this.createRandomProperty(..., ...);
...
}
createRandomProperty(name, generator) {
let value = generator.newValue();
Object.defineProperty(this, name, {
get: () => {
let _ = value;
value = generator.newValue();
return _;
}
});
}
}
假设您明智地编写了数据伪造者,我们现在可以致电:
let myobj = new MyObject();
console.log(myobj.background); // some value
console.log(myobj.background); // some completely different value
console.log(myobj.background); // again some completely different value
当然,您不需要单独的数据伪造者,但是将其伪装成单独的东西意味着您的代码将保持整洁且易于维护。
答案 3 :(得分:0)
我认为最简单的方法是在对象上使用方法,并用新对象覆盖它们。这为您提供了动态值,并解决了重新定义getter的开销。唯一需要注意的是,您必须调用方法而不是读取属性,即用baseObj.border()
而不是baseObj.border
。
var div = document.querySelector("#div");
getNewStyle = document.querySelector("#getNewStyle");
changeStyle1 = document.querySelector("#changeStyle1");
let baseObj = {
border: () => Math.round(Math.random() * 10 + 3),
background: () => 'hsl(' + Math.random() * 360 + 'deg 100% 50%)'
}
const draw = overwriteObj => {
if (overwriteObj) {
baseObj = {
...baseObj,
...overwriteObj
}
}
div.style.borderWidth = baseObj.border() + "px";
div.style.backgroundColor = baseObj.background();
}
getNewStyle.onclick = () => {
draw();
};
changeStyle1.onclick = () => {
draw({
border: () => Math.round(Math.random() * 55 + 20)
});
};
#div {
width: 300px;
height: 300px;
box-sizing: border-box;
border-style: dashed;
border-radius: 50%;
}
<div id="div"></div>
<button id="getNewStyle">getNewStyle</button>
<br>
<button id="changeStyle1">changeStyle1</button>
答案 4 :(得分:-1)
我发现了我对这些特性的增强和随机性的误解和误解。
通过将对象文字作为参数提供给函数(计算):
calculate({
border: Math.round(Math.random() * 55 + 20)
})
border属性已被处理,无法确定该值背后的计算结果。
可能的解决方案,实际上是将工厂传递给calculate函数的人,以便您可以通过相同的计算获得多个对象。
或者感谢@cgTag和@Bergi以及Mike'Pomax'Kamermans,有很多解决方法。