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

时间:2018-12-31 17:10:48

标签: javascript javascript-objects

通用说明

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

我要完成的事情的清单

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

基于代码的详细说明

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> 

问题/杂项。

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

新年快乐!

5 个答案:

答案 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,有很多解决方法。