我有一个骰子滚动机器人,通过var roll = new Roll('4#2d20+3')
吐出结果。该构造函数使对象具有从字符串参数中解析出来的属性,类似于:
aRoll = {
text: '4#2d20+3',
times: 4,
dice: 2,
sides: 20,
modifier: 3,
roll: function() {...}
}
roll()
方法应该使用对象的属性来生成结果数组。这是一个学习JavaScript新功能的练习,所以我很好奇如何最好地完成这个。
旧的,程序化的方式:
this.roll = function() {
var total = 0;
for (var i=0; i < this.dice; i++) {
total += Math.floor(Math.random() * this.sides) + 1;
}
return total;
}
我尝试新的Array
功能迭代:
this.roll = () => Array(this.dice).fill(0).reduce(state => {
result + Math.floor(Math.random() * state.sides) + 1;
}, this);
这种方式有效,但Array(x).fill(0).reduce(...
是一个丑陋的黑客,将this
作为state
传递似乎是一个标志,我做错了。
我应该使用Array
方法吗?或者for
循环仍然是最简洁的方法吗?
答案 0 :(得分:2)
重复一次n次函数的一种方法是
Array.from(Array(n), fn)
为了使所有这些更具可读性,您可以定义,例如
let times = (n, fn) => Array.from(Array(n), fn);
let rand = n => Math.floor(Math.random() * n) + 1;
let sum = a => a.reduce((x, y) => x + y);
然后
roll = function() {
return sum(
times(this.dice,
rand.bind(0, this.sides)));
}
答案 1 :(得分:1)
我想我已经弄明白这应该怎么做了。
第一期很简单:do not use arrow functions as methods:
箭头函数不会创建自己的
this
上下文,因此this
在封闭的上下文中具有其原始含义。
this
是面向对象的全部要点,所以打破它是一个坏主意。将this
作为map()
的第二个参数传递确实是代码气味。
第二个问题:不是滥用reduce()
的初始值参数和this
伪造context
对象,而是使用闭包:
function roll(sides) {
return (total) => {
total + Math.floor(Math.random() * sides) + 1;
};
}
someArray.map(roll(this.sides));
当您将回调作为参数传递,但需要动态地为其提供调用者不提供的数据时,闭包是典型的解决方案。
对于第三个问题,将数组填充为对象属性的大小,以便多次调用一个函数...
没有内置的样板方式。 :•)@georg提供了一个干净的implementation of a times()
function,让我想起Ruby的Number.times()
,如果你有兴趣的话。