如果functionA是另一个functionB的参数,而functionB有一个调用functionA的循环,我们如何重复调用functionA而不是将functionA存储为常量var?
function rollDie() {
var die = [1, 2, 3, 4, 5, 6];
return die[Math.floor(Math.random() * values.length)];
}
function rollFalseDie() {
var falseDie = [1, 1, 4, 4, 4, 4];
return falseDie[Math.floor(Math.random() * values.length)];
}
function rollDiceNTimes (function1, function2, n) {
if (n > 0) {
if (function1 > function2) return 1 + rollDiceNTimes(function1, function2, n-1);
else return rollDiceNTimes(function1, function2, n-1);
}
return 0;
}
我有两个函数代表一个真实和假模具的卷,一个函数将掷骰子N次并返回第一个函数的值大于第二个函数的值的次数。但是,当我运行rollDiceNTimes(rollDie(),rollFalseDie(),50)时,输出为0或50,这似乎表明存储了第一个值rollDie()和rollFalseDie()并进行了50次比较。
如何修改我的函数体,以便重复调用rollDie()和rollFalseDie(),同时仍然接受两个函数和一个数字N作为rollDiceNTimes()的参数?
答案 0 :(得分:1)
执行以下2项更改:
1)实际上将函数传递给第一次调用(删除作为参数传递的函数的括号)
rollDiceNTimes(rollDie, rollFalseDie, 50)
2)更改rollDiceNTimes以实际执行函数参数(通过在函数名称旁边添加括号)
function rollDiceNTimes (function1, function2, n) {
if (n > 0) {
if (function1() > function2()) return 1 + rollDiceNTimes(function1, function2, n-1);
else return rollDiceNTimes(function1, function2, n-1);
}
return 0;
}
如果你想要一些更加独立的步骤,这意味着和你一样:
function rollDiceNTimes (function1, function2, n) {
var value1 = function1();
var value2 = function2();
if (n > 0) {
if (value1 > value2) return 1 + rollDiceNTimes(function1, function2, n-1);
else return rollDiceNTimes(function1, function2, n-1);
}
return 0;
}
要明确:
function myFunction() {
return 42;
}
myFunction
- >名为“myFunction”的实际函数。将其视为“可执行对象”
myFunction()
- > 42(调用myFunction的结果)。例如,可以是一个数字(虽然有些函数可以返回其他函数,但这不是这种情况)
当您编写function1 > function2
时,您正在尝试比较函数对象(而不是每个函数的数字结果!),这在这里没什么意义。
但是你说你用这种方式调用主递归函数:
rollDiceNTimes(rollDie(), rollFalseDie(), 50)
所以这意味着实际参数是不是函数。它们是功能的结果。有了名字,你认为你传递了函数,但实际上并没有这样做。你在所有的递归链中传递固定值,一遍又一遍!
例如,如果第一次调用rollDie()
返回3,第一次rollFalseDie()
返回4,
rollDiceNTimes(rollDie(), rollFalseDie(), 50)
将是同一个电话:
rollDiceNTimes(3, 4, 50)
在这种情况下,它将运行“else”部分,因此return rollDiceNTimes(function1, function2, n-1);
与return rollDiceNTimes(3, 4, 49);
相同(因为您的可变名称“function1”和“function2”只是固定数字,不是功能。
依此类推,直到rollDiceNTimes(3,4,0),它将返回零。
相同的逻辑将使用1 + 1 + 1 ...(50次)迭代50次,如果前两个参数处于另一个顺序,则产生50次。
你也可以写if (function1() > function2())
,但我只是想把呼叫和比较分开来。
答案 1 :(得分:0)
最好有一个递归函数调用本身是函数的最后一个语句。目前尾部呼叫优化已被删除,但可能在将来再次添加。当tco回来时,编译器将实现递归调用。
因此rollDiceNTimes有一个名为recur的函数,如果1大于2并递减n
(滚动次数),它将调用自身递增计数器。如果n为零,它将返回计数器。
我删除了重复的rollDie
代码,并创建了一个名为dice
的函数,它接受一个用于骰子面的值数组,并返回一个函数,当被调用时将返回其中一个面(滚动骰子)。
function dice(faces) {
return function(){//return function
return faces[Math.floor(Math.random() * faces.length)];
}
}
function rollDiceNTimes (roll1,roll2, n) {
function recur(total,n){
if(n===0){
return total;
}
return recur(
total+(
//ternary operator (like an if statement but shorter)
(roll1()>roll2())
? 1
: 0),
n-1
);
}
return recur(0,n);
}
console.log(
rollDiceNTimes(
dice([1, 2, 3, 4, 5, 6]),
dice([1, 1, 4, 4, 4, 4]),
50
)
);
您还可以将滚动后要执行的功能传递给rollDiceNTimes
,并且不仅获得1大于2的次数,而且还获得两个滚动骰子的平均值:
function dice(faces) {
return function(){//return function
return faces[Math.floor(Math.random() * faces.length)];
}
}
function rollDiceNTimes (afterRollFn, roll1,roll2, n) {
function recur(total,n){
if(n===0){
return total;
}
return recur(
afterRollFn(roll1(),roll2()),
n-1
);
}
return recur(0,n);
}
console.log(
"One larger than two",
rollDiceNTimes(
(function (total) {//IIFE with total in closure
return function (one,two) {
//ternary operator (like an if statement but shorter)
if (one>two) {
total = total + 1;
}
return total;
}
}(0)),
dice([1, 2, 3, 4, 5, 6]),
dice([1, 1, 4, 4, 4, 4]),
50
)
);
console.log(
"Average of one and two",
rollDiceNTimes(
(function (timesRolled,totalOne,totalTwo){//IIFE with totals in closure
return function (one,two) {
timesRolled = timesRolled+1;
totalOne=totalOne+one;
totalTwo=totalTwo+two;
//average of both
return [totalOne/timesRolled,totalTwo/timesRolled]
};
}(0,0,0)),
dice([1, 2, 3, 4, 5, 6]),
dice([1, 1, 4, 4, 4, 4]),
50
)
);