繁体   English   中英

Javascript:获取具有随机属性值的对象

[英]Javascript: Get object with randomized property values

通用说明

我正在寻找一种获取具有几个定义的属性和随机值的对象的方法,每次访问它们时它们都会改变。 另外,我想动态覆盖属性并找到一种获取新对象的方法。

我要完成的事情清单

  • 对象具有随机属性值
  • 可以使用新值创建“新实例”或新对象
  • 动态替换对象是可能的,并且以上两个条件仍然有效

基于代码的详细说明

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

这样,I baseObj是对保持不变的对象的引用。

换句话说,无论您使用baseObj的频率如何或访问其属性的频率如何,其值都不会改变,因为Math.random()已执行并且该值已分配给objects属性。

为了解决这个问题,我将输出包装到一个可以调用的函数中,并获得一个具有新值的新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> 

问题/杂项。

有没有更好的方法来获取将其放入函数的新值? 如果您认为问题更容易理解,请随时进行编辑。

新年快乐!

有比将新值放入函数中更好的方法吗?

不,产生新值的函数(称为“工厂”)是最简单的方法。

我现在正在努力的要点是如何针对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);
}

我必须承认我不太了解这个问题,但是鉴于其他答案,我认为我会添加不同的意见 ,这似乎是一个意见问题。

您可以定义一个对象,该对象使用生成随机属性值的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

现在,我这就是您想要的。

这里没有什么太复杂的:创建一个对象或使用一个类,然后使用“ 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

当然,您不需要单独的数据伪造者,但是将代码伪造为单独的事物意味着您的代码将保持整洁且易于维护。

我认为最简单的方法是在对象上使用方法并用新对象覆盖它们。 这为您提供了动态值,并解决了重新定义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> 

我发现了我对这些特性的增强和随机性的误解和误解。

通过将对象文字作为参数提供给函数(计算):

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

border属性已被处理,无法确定该值背后的计算结果。

可能的解决方案,实际上应该是将工厂传递给calculate函数,以便您可以使用相同的计算获得多个对象。

或者感谢@cgTag和@Bergi和Mike'Pomax'Kamermans,有很多解决方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM