数组的惯用填充只要 属性 的值
Idiomatic population of an array as long as a property's value
我有一个掷骰子的机器人,可以通过 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(...
是一个丑陋的 hack,并且将 this
作为 state
传递似乎是我做错事的标志。
我应该使用 Array
方法吗?或者 for
循环仍然是完成此任务的最干净的方法吗?
重复一个函数 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)));
}
我想我想出了这个“应该”怎么做。
第一期很简单:do not use arrow functions as methods:
An arrow function does not create its own this
context, so this
has its original meaning from the enclosing context.
this
是面向对象的重点,所以打破它是个坏主意。将 this
作为 map()
的第二个参数传递确实是一种代码味道。
第二个问题:与其滥用 reduce()
的初始值参数 this
来伪造 context
对象,不如使用关闭:
function roll(sides) {
return (total) => {
total + Math.floor(Math.random() * sides) + 1;
};
}
someArray.map(roll(this.sides));
当您将回调作为参数传递,但需要动态地为它们提供调用者未提供的数据时,闭包是经典的解决方案。
至于第三期,填充一个对象大小的数组属性,为了多次调用一个函数...
没有内置的样板方式。 :•) @georg 好心地提供了一个干净的 让我想起了 Ruby 的 Number.times()
,如果你有兴趣的话。
我有一个掷骰子的机器人,可以通过 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(...
是一个丑陋的 hack,并且将 this
作为 state
传递似乎是我做错事的标志。
我应该使用 Array
方法吗?或者 for
循环仍然是完成此任务的最干净的方法吗?
重复一个函数 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)));
}
我想我想出了这个“应该”怎么做。
第一期很简单:do not use arrow functions as methods:
An arrow function does not create its own
this
context, sothis
has its original meaning from the enclosing context.
this
是面向对象的重点,所以打破它是个坏主意。将 this
作为 map()
的第二个参数传递确实是一种代码味道。
第二个问题:与其滥用 reduce()
的初始值参数 this
来伪造 context
对象,不如使用关闭:
function roll(sides) {
return (total) => {
total + Math.floor(Math.random() * sides) + 1;
};
}
someArray.map(roll(this.sides));
当您将回调作为参数传递,但需要动态地为它们提供调用者未提供的数据时,闭包是经典的解决方案。
至于第三期,填充一个对象大小的数组属性,为了多次调用一个函数...
没有内置的样板方式。 :•) @georg 好心地提供了一个干净的 Number.times()
,如果你有兴趣的话。