Урок 15: Продвинутые функции
Функции являются основой программирования на JavaScript. В этом уроке мы рассмотрим две важные концепции: замыкания и рекурсию.
Замыкания
Замыкание — это функция, которая имеет доступ к переменным из своей внешней функции даже после того, как эта внешняя функция завершила выполнение. Это позволяет функции «замыкать» в себе переменные из области видимости, в которой она была объявлена.
// Пример замыкания
function makeCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
let counter = makeCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
В этом примере функция makeCounter
создает замыкание, которое сохраняет доступ к переменной count
. Каждый вызов counter
увеличивает count
и возвращает его значение.
Рекурсия
Рекурсия — это процесс, при котором функция вызывает саму себя. Рекурсивные функции должны иметь условие завершения, чтобы избежать бесконечного цикла вызовов.
Факториал
Функция вычисления факториала числа является классическим примером рекурсивной функции.
// Пример рекурсивной функции для вычисления факториала
function factorial(n) {
if (n === 0) {
return 1;
} else {
return n * factorial(n - 1);
}
}
console.log(factorial(5)); // 120
В этом примере функция factorial
вызывает саму себя до тех пор, пока n
не станет равным 0. При каждом вызове n
уменьшается на 1, и произведение всех значений n
возвращается в конце.
Числа Фибоначчи
Еще одним примером рекурсивной функции является вычисление чисел Фибоначчи.
// Пример рекурсивной функции для вычисления чисел Фибоначчи
function fibonacci(n) {
if (n <= 1) {
return n;
} else {
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
console.log(fibonacci(6)); // 8
В этом примере функция fibonacci
вызывает саму себя для вычисления суммы двух предыдущих чисел Фибоначчи до тех пор, пока n
не станет равным 0 или 1.
Примеры использования замыканий и рекурсии
Рассмотрим несколько примеров использования замыканий и рекурсии в различных ситуациях.
// Пример 1: Замыкание для создания приватных переменных
function createPerson(name) {
let age = 0;
return {
getName: function() {
return name;
},
getAge: function() {
return age;
},
birthday: function() {
age++;
}
};
}
let person = createPerson('Alice');
console.log(person.getName()); // Alice
console.log(person.getAge()); // 0
person.birthday();
console.log(person.getAge()); // 1
// Пример 2: Рекурсивная функция для подсчета суммы элементов массива
function sumArray(arr) {
if (arr.length === 0) {
return 0;
} else {
return arr[0] + sumArray(arr.slice(1));
}
}
let numbers = [1, 2, 3, 4, 5];
console.log(sumArray(numbers)); // 15
Упражнения
Упражнение 1: Замыкание для счетчика
Создайте функцию createCounter
, которая возвращает объект с методами increment
и getValue
. Метод increment
должен увеличивать внутренний счетчик на 1, а метод getValue
должен возвращать текущее значение счетчика.
Решение:
// Определение функции createCounter
function createCounter() {
let count = 0;
return {
increment: function() {
count++;
},
getValue: function() {
return count;
}
};
}
let counter = createCounter();
counter.increment();
console.log(counter.getValue()); // 1
counter.increment();
console.log(counter.getValue()); // 2
Объяснение: Мы создали функцию createCounter
, которая возвращает объект с методами increment
и getValue
. Метод increment
увеличивает внутренний счетчик, а метод getValue
возвращает текущее значение счетчика.
Упражнение 2: Рекурсивная функция для вычисления суммы цифр числа
Создайте рекурсивную функцию sumDigits
, которая принимает число и возвращает сумму его цифр. Например, sumDigits(123)
должно вернуть 6
(1 + 2 + 3).
Решение:
// Определение функции sumDigits
function sumDigits(num) {
if (num === 0) {
return 0;
} else {
return num % 10 + sumDigits(Math.floor(num / 10));
}
}
console.log(sumDigits(123)); // 6
Объяснение: Мы создали функцию sumDigits
, которая использует рекурсию для суммирования цифр числа. Если число равно 0, функция возвращает 0. В противном случае функция добавляет последнюю цифру числа (используя оператор %
) к результату рекурсивного вызова функции с числом, уменьшенным на последнюю цифру (используя Math.floor
).