Я думаю, вы не полностью понимаете каждую концепцию программирования, которую вы использовали в своем коде.
Кроме того, ваш исходный код содержит опечатку: a.firstNum++;
где он должен читать firsNum
как в во всех остальных местах.
Давайте разберем ваш код на отдельные задачи.
Рекурсия
Рекурсия означает, что функция вызывает сама себя. Рекурсия - это один из способов вычисления, итерации или обхода данных. Другой - итерация с использованием циклов, таких как 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,
};
Хотя это само по себе выиграло ' t решить проблему. Продолжайте читать.
Обратные вызовы
Обратные вызовы - это функции, переданные как параметры функции, свойства объекта или элементы массива другим функциям.
Обратные вызовы позволяют вам решить, какую функцию вызывать во время время выполнения без необходимости реализовывать поведение ветвления с использованием операторов 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() {
// ...
});
С обратными вызовами очень важно gr asp разница между передачей результата вызова функции и сама функция:
callTheCallback(someCallback); // Callback function passed
callTheCallback(someCallback()); // Result of a function call passed
Обратите внимание, что передача результата вызова функции может быть вполне допустимой, если возвращаемое значение само является функцией. Это также не редкость в программировании.
Обратные вызовы часто используются для инверсии управления (Io C) в целом и асинхронного программирования в частности.
Примеры функций обратного вызова:
В вашем случае fun()
передается как обратный вызов третьего параметра в add()
.
Теперь, когда вы знаете, как использовать рекурсию и обратные вызовы, есть все еще semanti c ошибки в вашем коде ...
Семантические ошибки
В отличие от синтаксических ошибок (неправильная грамматика кода) семантические ошибки - это ошибки со смыслом кода.
Интерфейс 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) {
// ...
}
Приведенный выше стиль комментариев называется JsDo c: https://jsdoc.app
Обратите внимание на использование собственных имен для функций, переменных и параметров. Собственные имена помогают документировать код без написания явных комментариев к документации.
Исправление ошибки
Имея ограниченные знания о том, что вы действительно хотели достичь, можно только предполагать. Я предполагаю, что add()
, хотя его имя и параметры выглядят разумно, реализован неправильно. Ваша проблема может быть решена путем правильного вызова обратного вызова (fun()
):
function add(obj, callback) {
return callback(obj);
}
И:
add(object, fun);
Поскольку нам нужен объект, add()
теперь ожидает его как единый параметр.
Что ж, теперь это не имеет большого смысла. fun()
может быть вызван непосредственно из init()
, а не через ссылку обратного вызова, а add()
имеет запутанное имя.
Я не буду дальше строить предположения о ваших намерениях и как реализовать альтернативные решения проблемы.
Что вы узнали
- О Сеть разработчиков Mozilla
- Как работает рекурсия
- Функции могут быть переданы как параметры и назначены переменным или свойствам
- Чтение кода
- Преимущества документирования кода и правильного наименования функций и переменных