我认为您并没有完全理解您在代码中使用的每个编程概念。
除此之外,您的原始代码包含一个错字:a.firstNum++;,它应该像在所有其他地方一样显示为 firsNum。
让我们将您的代码分解为不同的关注点。
递归
Recursion 表示函数调用自身。递归是一种计算、迭代或遍历数据的方法。另一种是使用while 或for 之类的循环进行迭代。
让我们看看这个简化的例子:
function recurse(counter) {
console.log(counter);
recurse(counter + 1);
}
recurse(0);
这将无限期地调用recurse(),因为没有什么可以阻止它调用自己。递归和迭代都需要一些停止条件来中断递归。
如果您想在某个值处停止,您只需要在满足该条件之前调用该函数:
function recurse(counter) {
console.log(counter);
if (counter < 42) {
recurse(counter + 1);
}
}
recurse(0);
这只会递归和递增,直到达到 42。
您甚至可以使用函数本身传递停止条件:
function recurse(counter, maxValue) {
console.log(counter);
if (counter < maxValue) {
recurse(counter + 1, maxValue); // maxValue gets passed along
}
}
recurse(0, 42);
要使您的递归函数在某个值处停止,您必须添加这样一个条件:
function fun(a) {
a.firstNum++;
a.sum += a.firstNum;
if (a.sum < a.maxNum) {
fun(a);
}
}
然后您必须确保您的对象指定条件:
let object = {
maxNum: 3, // stop condition added
firsNum: 1,
sum: 0,
};
虽然这本身并不能解决问题。继续阅读。
回调
回调是作为函数参数、对象属性或数组元素传递给其他函数的函数。
回调允许您决定在运行时调用什么函数,而无需使用 if 或 switch 语句实现分支行为,并且在编写时需要某些函数名称。
function someCallback() { /* ... */ }
function callTheCallback(callback) {
callback(); // Execute the parameter as a function
}
callTheCallback(someCallback);
let someCallbackReference = someCallback;
// Call the same function but indirectly via a variable
callTheCallback(someCallbackReference);
在上面的示例中,someCallback 可以间接源自其他对象。
您甚至可以直接将函数表达式指定为回调:
callTheCallback(function() {
// ...
});
对于回调,掌握传递函数调用结果和函数本身之间的区别至关重要:
callTheCallback(someCallback); // Callback function passed
callTheCallback(someCallback()); // Result of a function call passed
请注意,如果返回值本身是一个函数,则传递函数调用的结果可能是完全有效的。这在编程中也很常见。
回调通常用于inversion of control (IoC),特别是asynchronous programming。
回调函数示例:
在您的情况下,fun() 作为第三个参数回调传递给add()。
既然您知道如何使用递归和回调,您的代码中仍然存在语义错误...
语义错误
与句法错误(错误的代码语法)相反,语义错误是与代码含义有关的错误。
add()的接口
分析你的函数API:
function add(a, b, callback) {
return /* some value - callback() call removed for simplicity */;
}
add() 接受三个参数并返回一个值。第三个参数名为“回调”,因此应该是一个函数。
您对add() 的调用看起来很合理,尽管您没有使用返回值(这不一定是错误)。
add(1, object.firsNum, fun);
add()的实现
由于add() 的参数没有记录,所以你的意图是模棱两可的。
名称以及有两个参数a 和b 的事实导致人们假设应该添加这两个值。你做得很好:
return callback(a + b);
但是!您作为回调函数传递的内容 - fun() - 需要不同的参数,而不是数字。 fun() 需要一个对象。
正确记录它看起来像这样:
/**
* Recursively sum values until a maximum value is reached.
*
* @param {Object} a object containing the sum, the increment and the max value
* @param {Number} a.firsNum start value
* @param {Number} a.maxNum the maxium value up to which to add "firsNum" to "sum"
* @param {Number} a.sum the summed value, shall be 0 initially
* @returns {undefined} nothing is returned
*/
function fun(a) {
// ...
}
上面的评论风格叫做JsDoc:https://jsdoc.app
注意为函数、变量和参数使用正确的名称。正确的名称有助于记录代码,而无需编写明确的文档 cmets。
修复错误
由于对您真正想要达到的目标了解有限,因此只能推测。我假设add(),虽然它的名称和参数看起来很合理,但实现错误。您的问题可以通过正确调用回调 (fun()) 来解决:
function add(obj, callback) {
return callback(obj);
}
还有:
add(object, fun);
由于我们需要对象add(),现在期望它作为单个参数。
现在这已经没有多大意义了。 fun() 可以直接从 init() 内部调用,而不是通过回调引用,add() 的名称令人困惑。
我不会进一步推测您的意图是什么以及如何实施该问题的替代解决方案。
你学到了什么