Транскрипт урока
Мы уже знакомы со способом называть что-то, используя константы. Например, это константа pi со значением 3.14.
После этой строки, каждый раз, когда мы видим pi, мы знаем, что её значение 3.14. Она называется константой, потому что, ээм, она неизменна, постоянна. После этой строки pi всегда будет 3.14, это никогда не изменится. Именно поэтому по аналогии с бумагой я использую ручку.
Это может показаться ограничением, но вообще — это довольно хорошее свойство. Изменение того, что мы уже создали — сложная задача. Представьте, что пишете код, используя константу, в значении которой не уверены.
Тем не менее, иногда вам может потребоваться изменить уже существующие данные или, другими словами, их значения. Допустим, вы хотите повторить что-то 5 раз. Один способ — выполнять повторы, отсчитывая до пяти, а затем остановиться. Для этого вам потребуется что-нибудь для хранения счётчика этого меняющегося числа. Константа не будет в таком случае работать — она неизменна, вы не можете изменить её значение после того, как уже создали её.
Поэтому в JavaScript и многих других языках программирования существует идея переменной. Можно представить ее в виде такой же бумажки, на которой имя написано ручкой, но значение — карандашом. В любой момент можно заменить значение на другое.
Можно посчитать факториал с помощью переменной вот так:
Создать переменную — просто, она выглядит как константа, только вместо const мы пишем let. Мы позволяем ей быть чем-то и это не навсегда.
Затем мы изменяем значение factorial. Мы бы такого не смогли сделать, если бы factorial был константой. Эта строка означает "изменить значение переменной факториал, на результат умножения факториала на 2". Теперь JavaScript умножает factorial на 2 и хранит этот результат в переменной factorial. Раньше factorial был 1, а теперь это 2.
Мы повторяем это ещё трижды, каждый раз умножая полученное значение на следующее целое число: на 3, на 4 и на 5. Это то, что вы возможно делаете в уме, когда умножаете числа. Вероятно, вы не думали об этом так чётко, но это неплохой способ описания процесса вычисления, если бы вам было нужно объяснить его.
Идея использования счётчика для повторения чего-то множество раз — распространённая в программировании, и большинство языков программирования имеют для этого "циклы". Давайте рассмотрим один тип цикла — "цикл while". Это блок кода, который повторяется, пока удовлетворяется какое-то условие.
Представьте фермера, который работает от рассвета до заката. Другими словами, он работает пока солнце в небе. Вы можете записать:
while (sun is up) {
work
}
Конечно, это не настоящий JavaScript, это просто чтобы показать идею. Эта строка "work" будет повторяться снова и снова, пока солнце над горизонтом. Это значит после каждого повторения нам нужно проверять, действительно ли солнце в небе, и остановиться если это не так. Другими словами: проверить — исполнить, проверить — исполнить, и так далее.
Вот функция факториала с переменными и циклом вместо рекурсии.
О-о, что тут происходит? Во-первых, мы создали две переменные: одна для счётчика, чтобы считать от 1 до верхнего предела, а вторая для текущего результата.
Затем начинается главная часть: цикл while, который повторяется, пока счётчик меньше или равен n — числу, переданному в эту функцию. Код, который повторяется, простой: мы меняем значения наших двух переменных. Текущий результат умножается на счётчик, а счётчик увеличивается на 1.
В какой-то момент это условие — "счётчик меньше или равен n" — станет ложным, цикл больше не будет повторяться, а программа перейдёт к следующему этапу — return result. К этому моменту результат станет ответом, потому что за время всех повторов в цикле, результат умножался на 1, затем на 2, 3 и так далее, пока не достиг значения n, каким бы оно ни было.
Давайте посмотрим, что компьютер делает шаг за шагом, когда мы вызываем факториал 3.
- Взять один аргумент — 3, известный внутри, как n
- Создать переменную counter, установить значение 1
- Создать переменную result, установить значение 1
- Проверить: в счётчике — 1, это меньше или равно n, поэтому
- Умножить result на counter и положить ответ — 1 — в result
- Добавить 1 к counter и положить ответ — 2 — в counter
- Вернуться и проверить: counter — 2, это меньше или равно n, поэтому
- Умножить result на counter и положить ответ — 2 — в result
- Добавить 1 к counter и положить ответ — 3 — в counter
- Вернуться и проверить: counter — 3, это меньше или равно n, поэтому
- Умножить result на counter и положить ответ — 6 — в result
- Добавить 1 к counter и положить ответ — 4 — в counter
- Вернуться и проверить: counter — 4, это не меньше и не равно n, поэтому остановить повтор и перейти к следующей строке
- Вернуть result — 6
Компьютер выполняет такие операции в миллиарды раз быстрее, но по сути это выглядит именно так. Общее название такого вида сформулированных повторений — "итерация". Наша программа использует итерацию, чтобы рассчитать факториал.
В прошлый раз мы рассматривали итеративный процесс с рекурсией, а в этот — итеративный процесс без рекурсии.
Оба используют технику итерации, но с рекурсивными вызовами нам не нужно менять значения, мы просто передаём новые значения в следующий вызов функции. А эта функция факториала не имеет рекурсивных вызовов вообще, поэтому все трансформации должны происходить внутри единственного экземпляра, единственной функциональной коробки. У нас нет выбора, кроме как менять значения содержимого.
Стиль программирования, который вы видели в предыдущих уроках, называется "декларативным". Сегодняшний стиль, с изменением значений, называется "императивным".
Сравните рекурсивный и нерекурсивный факториалы:
Эта рекурсивная функция — декларативная — она как описание факториала. Она объясняет, что такое факториал.
Это нерекурсивная итеративная функция, и она императивная — она описывает, что делать, чтобы найти факториал.
Слово декларативный происходит от латинского "clarare" — разъяснять, заявлять, делать объявление. Вы разъясняете: я хочу, чтобы факториал n был n умножить на факториал n-1.
Слово императивный происходит от латинского "imperare", что значит "командовать". Вы приказываете чётко передвигаться по шагам — умножать это на это, пока идёт отсчёт и запоминать какие-то числа.
Декларативное — это что. Императивное — это как.
Писать декларативный код, в целом, лучший подход. Ваш код будет легче читать, понимать и делать что-то новое опираясь на него. Некоторые языки провоцируют вас использовать тот или иной подход, а некоторые вообще не оставляют выбора.
Но в итоге вам нужно будет научиться оценивать, когда императивный подход принесет больше проблем чем решений.
Следить за изменениями – сложно, и буквально несколько переменных могут сделать систему очень сложной для понимания.
От изменения состояния появляется гора багов, а оператор присваивания (assignment statements), который создает изменения, часто является причиной всего зла во вселенной.
Дополнение к уроку
var vs let
Кроме let существует другой способ определения переменных: var a = 5. Этот способ был единственным до появления стандарта ES6, но в современном JavaScript он является устаревшим, и let полностью заменил его.
let и var по-разному влияют на видимость переменной, и использование var сегодня нежелательно. let был создан как более правильная альтернатива старому способу.
Отладка: Как найти и исправить ошибки
Наделать ошибок очень легко, когда приходится справляться с переменными, изменять их, отслеживать и всякое такое. Особенно в зацикленном процессе. Прекрасный способ разобраться с тем, что происходит — использовать простейшую технику для отладки — console.log. Вспомните, эта функция выводит в консоль то, что ей передают.
Например, я пытаюсь разобраться, что происходит внутри цикла while:
Добавлю сюда console.log:
Теперь, каждый раз, когда повторяется этот блок кода, переменная result будет выводиться на экран. Давайте посмотрим:
(Я запускаю функцию с n равным 3)
В каждом шаге result — это 1. Не верно — result должен возрастать на каждом шаге… Ок, значит вероятная проблема, в строке, где result меняется. Так и есть! У меня result = result * result, а мне нужно умножить result на counter, а не на result.
Теперь всё работает! Теперь я вижу шаги и последний шаг выдал верный ответ: 3! это 6. Используйте console.log абсолютно везде. Это ваш лучший друг :-)
Бесконечные циклы
Поскольку цикл while только проверяет состояние, мы можем создать бесконечные циклы, если сделаем состояние всегда истинным.
Этот код будет выводить на экран "Десять всё ещё больше чем 5" пока не сгорит вселенная или пока вы не закроете программу, ну или пока компьютер не израсходует всю свою память — что бы ни случилось первым. Поскольку состояние 10 > 5 всегда истинно.
Есть еще более простой способ сделать бесконечный цикл — while (true) { ... }. При этом true всегда истинный.
Иногда ваши циклы будут бесконечными, даже если вы этого не планировали. Это общая проблема, и она указывает только на то, что внутри цикла вы забыли изменить проверяемую деталь. Например, если я удалю строку counter = counter + 1 из цикла в сегодняшнем уроке:
… у меня получится бесконечный цикл: counter никогда не меняется, поэтому если counter <= n, условие всегда будет истинно.
Выводы
Переменные подобны константам, но вы можете изменить их значения в любой момент.
Циклы — это повторяющиеся блоки кода. Цикл while — это блок, повторяющийся пока какое-то состояние истинно.
Вот факториал функции с циклом while:
Идея: сделать counter = 1, затем умножать result на counter повторно, пока идёт отсчёт до n (число, передаваемое функции). Когда counter станет больше, чем n — остановиться. К тому моменту result будет ответом.
Это итерация — сформулированное повторение кода. Разные языки по-разному выполняют итерацию. Цикл while — это один из способов, который предлагает JavaScript.
Декларативное vs. императивное программирование
Сравните рекурсивный факториал (из 9 урока) и нерекурсивный факториал (из сегодняшнего):
Эта рекурсивная функция — декларативная — она как бы определение (трактование, характеристика) факториала. Она декларирует, что такое факториал.
Эта нерекурсивная итеративная функция — императивная — описание того, что нужно делать, чтобы найти факториал.
Слово декларативный происходит от латинского "clarare" — разъяснять, заявлять, делать объявление. Вы разъясняете: я хочу, чтобы факториал n был n раз факториалом n-1.
Слово императивный происходит от латинского "imperare", что значит "командовать". Вы приказываете чётко передвигаться по шагам — умножать это на это, пока идёт отсчёт и запоминаются какие-то числа.
Декларативное — это что. Императивное — это как.
Писать декларативный код, в целом, лучший выбор. Ваш код будет легче читать, понимать и делать что-то новое опираясь на него. Но иногда у вас нет выбора.
От изменения состояния* появляется гора багов, а инструкции (операторы) присваивания (assignment statements), которые создают изменения, часто являются коренными причинами всего зла во вселенной.
Поэтому, когда дело доходит до инструкций присваивания, действуйте осторожно.
<!DOCTYPE html>
<html class="h-100" data-bs-theme="light" data-mantine-color-scheme="light" lang="ru" prefix="og: https://ogp.me/ns#">
<head>
<meta content="width=device-width, initial-scale=1.0" name="viewport">
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<link crossorigin="true" href="https://cdn.hexlet.io" rel="preconnect">
<link href="https://mc.yandex.ru" rel="preconnect">
<meta content="aa2vrdtq64dub8knuf83lwywit311w" name="facebook-domain-verification">
<link href="/favicon.ico" rel="icon" sizes="any">
<link href="/favicon.svg" rel="icon" type="image/svg+xml">
<link href="/apple-touch-icon.png" rel="apple-touch-icon">
<link href="/manifest.webmanifest" rel="manifest">
<script>
//<![CDATA[
window.gon={};gon.ym_counter="25559621";gon.is_bot=true;gon.applications={};gon.current_user={"id":null,"last_viewed_notification_id":null,"email":null,"state":null,"first_name":"","last_name":"","created_at":"2026-02-26 17:11:43 UTC","current_program":null,"current_team":null,"full_name":"","guest":true,"can_use_paid_features":false,"is_hexlet_employee":false,"sanitized_phone_number":"","can_subscribe":true,"can_renew_education":false};gon.token="cJTdE1GSp4r3YpVGaAofn_qn862_trl9wsng8UB5QiOfRRYko-wK6kEhsd5kBe_oOq7eB7eBR99_KXqlEn6lTQ";gon.locale="ru";gon.language="ru";gon.theme="light";gon.rails_env="production";gon.mobile=false;gon.google={"analytics_key":"UA-1360700-51","optimize_key":"GTM-5QDVFPF"};gon.captcha={"google_v3_site_key":"6LenGbgZAAAAAM7HbrDbn5JlizCSzPcS767c9vaY","yandex_site_key":"ysc1_Vyob5ZPPUdPBsu0ykt8bVFdzsfpoVjQChLGl2b4g19647a89","verification_failed":null};gon.social_signin=false;gon.typoreporter_google_form_id="1FAIpQLSeibfGq-KvWQ2Fyru-zkFFRVTLBuzXAHAoEyN1p49FtDmNoNA";
//]]>
</script>
<meta charset="utf-8">
<title>Переменные, декларативное и императивное программирование | Введение в программирование</title>
<meta name="description" content="Переменные, декларативное и императивное программирование / Введение в программирование: Изучаем новые термины: переменные, циклы и изменяемые данные. Учимся отличать декларативное программирование от императивного.">
<link rel="canonical" href="https://ru.hexlet.io/courses/introduction_to_programming/lessons/while/theory_unit">
<meta name="robots" content="noarchive">
<meta property="og:title" content="Переменные, декларативное и императивное программирование">
<meta property="og:title" content="Введение в программирование">
<meta property="og:description" content="Переменные, декларативное и императивное программирование / Введение в программирование: Изучаем новые термины: переменные, циклы и изменяемые данные. Учимся отличать декларативное программирование от императивного.">
<meta property="og:url" content="https://ru.hexlet.io/courses/introduction_to_programming/lessons/while/theory_unit">
<meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="NC-gTwERJIjihJslpvc-kJ40Do0reBpLHsApFNIpxKPb_mt482-J6FTHv72q-M7nXj0jJyNP5OmjILNAgC4jzQ" />
<script src="/vite/assets/inertia-INZxX8jp.js" crossorigin="anonymous" type="module"></script><link rel="modulepreload" href="/vite/assets/chunk-DsPFFUou.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/preload-helper-BJ4cLWpC.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/init-nkZBEvfU.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/ahoy-DrlRQ-1D.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/analytics-6pOtQ3OW.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/ErrorFallbackBlock-naDSYSy9.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Surface-DL2bpZA-.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/gon-D3e4yh1x.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/mantine-CGMYrt2Y.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/utils-DRqSHbQE.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/routes-CCH8ilKF.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/extends-C-EagtpE.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/inheritsLoose-BBd-DCVI.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/objectWithoutPropertiesLoose-DRHXDhjp.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/index.esm-DAqKOkZ0.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Button-CGPUux8l.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/CloseButton-D1euiPao.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Group-BX48WcuU.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Loader-BQEY8g6v.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Modal-Cy3HByv7.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/OptionalPortal-1Hza5P2w.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Stack-CtjJzfw4.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Textarea-Ck64llAy.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Box-B5-OOzBf.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/DirectionProvider-Dc9zdUke.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/events-DJQOhap0.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/use-reduced-motion-D2owz4wa.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/use-disclosure-zKtK5W1r.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/use-hotkeys-Cnc_Rwkb.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/random-id-DOQyszCZ.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/notifications.store-C-3AFSMn.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/exports-C_MrNx_T.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/axios-BEvgo0ym.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/dayjs.min-BkKovM-s.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/i18next-BlSq9s7B.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/client-U9M77rxp.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-dom-DaLxUz_h.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/useTranslation-Bx1Cdrkz.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/compiler-runtime-6XxiPFnt.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/jsx-runtime-CwjcCKJi.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-CkL4ZRHB.js" as="script" crossorigin="anonymous">
<link rel="stylesheet" href="/vite/assets/application-BqhCP46M.js" />
<script src="/vite/assets/application-Df9RExpe.js" crossorigin="anonymous" type="module"></script><link rel="modulepreload" href="/vite/assets/chunk-DsPFFUou.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/autocomplete-VMNbxKGl.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/routes-CCH8ilKF.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/createPopper-C3aM9r1M.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/js.cookie-D1-O8zkX.js" as="script" crossorigin="anonymous"><link rel="stylesheet" href="/vite/assets/application-C8HjmMaq.css" media="screen" />
<script>
window.ym = function(){(ym.a=ym.a||[]).push(arguments)};
window.addEventListener('load', function() {
setTimeout(function() {
ym.l = 1*new Date();
ym(window.gon.ym_counter, "init", {
clickmap: true,
trackLinks: true,
accurateTrackBounce: true,
webvisor: true
});
// Загружаем скрипт
var k = document.createElement('script');
k.async = 1;
k.src = 'https://mc.yandex.ru/metrika/tag.js';
document.head.appendChild(k);
ym(window.gon.ym_counter, 'getClientID', function(clientID) {
window.ymClientId = clientID;
});
}, 1500);
});
</script>
<!-- Google Tag Manager - deferred -->
<script>
// dataLayer stub сразу — пуши работают до загрузки скрипта
window.dataLayer = window.dataLayer || [];
// Сам скрипт — отложенно после load
window.addEventListener('load', function() {
setTimeout(function() {
dataLayer.push({'gtm.start': new Date().getTime(), event: 'gtm.js'});
var j = document.createElement('script');
j.async = true;
j.src = 'https://www.googletagmanager.com/gtm.js?id=GTM-WK88TH';
document.head.appendChild(j);
}, 1500);
});
</script>
<!-- End Google Tag Manager -->
</head>
<body>
<noscript>
<div>
<img alt="" src="https://mc.yandex.ru/watch/25559621" style="position:absolute; left:-9999px;">
</div>
</noscript>
<header class="sticky-top bg-body">
<nav class="navbar navbar-expand-lg">
<div class="container-xxl">
<a class="navbar-brand" href="/"><img alt="Логотип Хекслета" height="24" src="https://ru.hexlet.io/vite/assets/logo_ru_light-BpiEA1LT.svg" width="96">
</a><button aria-controls="collapsable" aria-expanded="false" aria-label="Меню" class="navbar-toggler border-0 mb-0 mt-1" data-bs-target="#collapsable" data-bs-toggle="collapse">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="collapsable">
<ul class="navbar-nav mb-lg-0 mt-lg-1">
<li class="nav-item dropdown">
<button aria-haspopup class="btn nav-link" data-bs-toggle="dropdown" type="button">
Все курсы
<span class="bi bi-chevron-down align-middle ms-1"></span>
</button>
<ul class="dropdown-menu">
<li>
<a class="dropdown-item d-flex py-2" href="/courses"><div class="fw-bold me-auto">Все что есть</div>
<div class="text-muted">117</div>
</a></li>
<li>
<hr class="dropdown-divider">
</li>
<li class="dropdown-item">
<b>Популярные категории</b>
</li>
<li>
<a class="dropdown-item py-2" href="/courses_devops">Курсы по DevOps
</a></li>
<li>
<a class="dropdown-item py-2" href="/courses_data_analytics">Курсы по аналитике данных
</a></li>
<li>
<a class="dropdown-item py-2" href="/courses_programming">Курсы по программированию
</a></li>
<li>
<a class="dropdown-item py-2" href="/courses_testing">Курсы по тестированию
</a></li>
<li>
<hr class="dropdown-divider">
</li>
<li class="dropdown-item">
<b>Популярные курсы</b>
</li>
<li>
<a class="dropdown-item py-2" href="/programs/devops-engineer-from-scratch">DevOps-инженер с нуля
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/go">Go-разработчик
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/java">Java-разработчик
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/python">Python-разработчик
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/qa-auto-engineer-java">Автоматизатор тестирования на Java
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/data-analytics">Аналитик данных
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/frontend">Фронтенд-разработчик
</a></li>
</ul>
</li>
<li class="nav-item dropdown">
<button aria-haspopup class="btn nav-link" data-bs-toggle="dropdown" type="button">
О Хекслете
<span class="bi bi-chevron-down align-middle"></span>
</button>
<ul class="dropdown-menu bg-body">
<li>
<a class="dropdown-item py-2" href="/pages/about">О нас
</a></li>
<li>
<a class="dropdown-item py-2" href="/blog">Блог
</a></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://special.hexlet.io/hse-research" role="button">Результаты (Исследование)
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://career.hexlet.io" role="button">Хекслет Карьера
</span></li>
<li>
<a class="dropdown-item py-2" href="/testimonials">Отзывы студентов
</a></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://t.me/hexlet_help_bot" role="button">Поддержка (В ТГ)
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://special.hexlet.io/referal-program/?promo_creative=priglasite-druzei&promo_name=referal-program&promo_position=promo_position&promo_start=010724&promo_type=link" role="button">Реферальная программа
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://special.hexlet.io/certificate" role="button">Подарочные сертификаты
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://hh.ru/employer/4307094" role="button">Вакансии
</span></li>
<li>
<span class="dropdown-item d-flex external-link" rel="noopener noreferrer nofollow" data-href="https://b2b.hexlet.io" data-target="_blank" role="button">Компаниям
</span></li>
<li>
<span class="dropdown-item d-flex external-link" rel="noopener noreferrer nofollow" data-href="https://hexly.ru/" data-target="_blank" role="button">Колледж
</span></li>
<li>
<span class="dropdown-item d-flex external-link" rel="noopener noreferrer nofollow" data-href="https://hexlyschool.ru/" data-target="_blank" role="button">Частная школа
</span></li>
</ul>
</li>
<li><a class="nav-link" href="/subscription/new">Подписка</a></li>
</ul>
<ul class="navbar-nav flex-lg-row align-items-lg-center gap-2 ms-auto">
<li>
<a class="nav-link" aria-label="Переключить тему" href="/theme/switch?new_theme=dark"><span aria-hidden="true" class="bi bi-moon"></span>
</a></li>
<li>
<span data-target="_self" class="nav-link external-link" data-href="/u/new" role="button"><span>Регистрация</span>
</span></li>
<li>
<span data-target="_self" class="nav-link external-link" data-href="https://ru.hexlet.io/session/new" role="button"><span>Вход</span>
</span></li>
</ul>
</div>
</div>
</nav>
</header>
<div class="x-container-xxxl">
</div>
<main class="mb-6 min-vh-100 h-100">
<div id="app" data-page="{"component":"web/courses/lessons/theory_unit","props":{"errors":{},"locale":"ru","language":"ru","httpsHost":"https://ru.hexlet.io","host":"ru.hexlet.io","colorScheme":"light","auth":{"user":{"id":null,"last_viewed_notification_id":null,"email":null,"state":null,"first_name":"","last_name":"","created_at":"2026-02-26T17:11:42.894Z","current_program":null,"current_team":null,"full_name":"","guest":true,"can_use_paid_features":false,"is_hexlet_employee":false,"sanitized_phone_number":"","can_subscribe":true,"can_renew_education":false}},"cloudflareTurnstileSiteKey":"0x4AAAAAAA15KmeFXzd2H0Xo","vkIdClientId":"51586979","yandexIdClientId":"88d071f1d3384eb4bd1deb37910235c7","formAuthToken":"XkEMBD6a5CPXqTzisCo-Xue0mqZ0ZQp-LVFFaXjZgEWxkMczzORJQ2HqGHq8Jc4pJ723DHxS9NyQsd89Kt5nKw","topics":[{"id":45907,"title":"https://ru.hexlet.io/code_reviews/298220?submission_id=377259\n\nРебята, здравствуйте. Консоль выдает сообщение status: finished → Упс, что то пошло не так, код работал слишком долго и был остановлен. Проверьте условия выхода из циклов.\n\nПроверяю код в devtools firefox - хорошо работает. В чем может быть проблема?\n","plain_title":"https://ru.hexlet.io/codereviews/298220?submissionid=377259 Ребята, здравствуйте. Консоль выдает сообщение status: finished → Упс, что то пошло не так, код работал слишком долго и был остановлен. Проверьте условия выхода из циклов. Проверяю код в devtools firefox - хорошо работает. В чем может быть проблема? ","creator":{"public_name":"Andrey Glushko","id":302475,"is_tutor":false},"comments":[{"creator":{"public_name":"Игнатий Байгулов","id":296547,"is_tutor":false},"id":103430,"body":"https://ru.hexlet.io/code_reviews/324273\nТа же проблема. Проверил со всеми значениями из теста в jsbin.com и прекрасно работает, но когда проделываю тоже самое, с тем же самым кодом здесь, то выдает сообщение status: finished → Упс, что то пошло не так, код работал слишком долго и был остановлен. Проверьте условия выхода из циклов. Спасибо\n\n","topic_id":45907},{"creator":{"public_name":"Andrey Glushko","id":302475,"is_tutor":false},"id":99176,"body":"**Максим Литвинов**, спасибо. Разобрался","topic_id":45907},{"creator":{"public_name":"Игнатий Байгулов","id":296547,"is_tutor":false},"id":103475,"body":"**Максим Литвинов**, да, большое спасибо за Ваш ответ. Это действительно так, и как вы уже ответили другому пользователю, тема \"Окружение\", затрагивающая область видимости переменных ещё ждёт впереди. Теперь я понял, ещё раз благодарю ;-)","topic_id":45907},{"creator":{"public_name":"Maksim Litvinov","id":198906,"is_tutor":true},"id":103454,"body":"**Игнатий Байгулов**, добрый день. Сейчас у вашей функции есть побочный эффект - она меняет значение внешней для нее переменной. Один вызов функции начинает влиять на другой, именно поэтому вы получаете такое неожиданное поведение. Все переменные, нужные только для работы функции, должны быть объявлены внутри функции","topic_id":45907},{"creator":{"public_name":"Maksim Litvinov","id":198906,"is_tutor":true},"id":99148,"body":"Добрый день. Такой вывод говорит о том, что у вас возник бесконечный цикл, который был автоматически прерван. Наверняка вы проверили не все варианты, которые проверяются в тестах. Попробуйте проверить ваша функцию с аргументом 1 ","topic_id":45907}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Переменные, декларативное и императивное программирование","entity_url":null,"active":true}},{"id":44249,"title":"https://ru.hexlet.io/code_reviews/280472\n\nне работает даже решение учителя. лигически все верно. дело в тестах думаю","plain_title":"https://ru.hexlet.io/code_reviews/280472 не работает даже решение учителя. лигически все верно. дело в тестах думаю ","creator":{"public_name":"Alexandr Savchenko","id":126518,"is_tutor":false},"comments":[{"creator":{"public_name":"Sergei Melodyn","id":162475,"is_tutor":true},"id":95822,"body":"**Alexandr Savchenko**, приветствую. Если вопрос решён и вам помог ответ участника сообщества, поддержите его, отметив как решение ;)","topic_id":44249},{"creator":{"public_name":"Maksim Litvinov","id":198906,"is_tutor":true},"id":95751,"body":"Добрый день. С тестами все норм. Вы удалили часть упражнения, которая уже была написана. Скопируйте свое решение и нажмите кнопку Сброс. Упражнение вернется в первоначальную форму. Затем вставьте свое решение между begin и end ","topic_id":44249}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Переменные, декларативное и императивное программирование","entity_url":null,"active":true}},{"id":25823,"title":"Что значит эта ошибка? \n Assignment can be replaced with operator assignment\n\nв этой строке\ndivisor = divisor + 1;","plain_title":"Что значит эта ошибка? Assignment can be replaced with operator assignment в этой строке divisor = divisor + 1; ","creator":{"public_name":"","id":210660,"is_tutor":false},"comments":[{"creator":{"public_name":"","id":210660,"is_tutor":false},"id":55376,"body":"спасиибо всем)","topic_id":25823},{"creator":{"public_name":"Сергей К.","id":5174,"is_tutor":false},"id":55371,"body":"Да, верно. Вообще таких операторов достаточно много. Можно заглянуть в [документацию](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Operators/Assignment_Operators).","topic_id":25823},{"creator":{"public_name":"Владислав Панферов","id":190488,"is_tutor":false},"id":55268,"body":"ESlint предлагает использовать вместо вашей записи такую: divisor += 1;","topic_id":25823},{"creator":{"public_name":"","id":210660,"is_tutor":false},"id":55363,"body":"divisor += 1 будет именно увеличить на 1?\nто есть если divisor += 2 это увеличить на 2, верно?))\n","topic_id":25823},{"creator":{"public_name":"","id":210660,"is_tutor":false},"id":55349,"body":"А что значит divisor += 1; подскажите пожалуйста","topic_id":25823},{"creator":{"public_name":"Maxim Dragaytsev","id":193174,"is_tutor":false},"id":55362,"body":"это короткая запись того что вы и написали, divisor = divisor + 1;\nв вашем случае можно еще использовать ++divisor; \n","topic_id":25823}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Переменные, декларативное и императивное программирование","entity_url":null,"active":true}},{"id":18014,"title":"Hi , i have only english keyboard so , my question is ....\nWhere i have problem in my code????\n// BEGIN (write your solution here)\nconst smallestDivisor = (n) => {\n let x = 1;\nlet y = 2;\nwhile (x!= 0) {\n x = n % y;\n y = y + 1;\n}\nreturn y;\n}\n// END\n","plain_title":"Hi , i have only english keyboard so , my question is .... Where i have problem in my code???? // BEGIN (write your solution here) const smallestDivisor = (n) => { let x = 1; let y = 2; while (x!= 0) { x = n % y; y = y + 1; } return y; } // END ","creator":{"public_name":"Даниил Плешков","id":181000,"is_tutor":false},"comments":[{"creator":{"public_name":"Александр О.","id":61806,"is_tutor":false},"id":38079,"body":"Добрый день! :)\n\n> Where i have problem in my code?\n\nПрямая или косвенная причина указавается в выводе тестов (влкадка `OUTPUT`): его надо проанализировать в первую очередь, пробовали это сделать, что он вам показывает?","topic_id":18014}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Переменные, декларативное и императивное программирование","entity_url":null,"active":true}},{"id":49587,"title":"Добрый день. Не могу разобраться, в чем ошибка в линтере - 5:31 error Expected to return a value at the end of arrow function consistent-return. \nссылка на ревью.\nhttps://ru.hexlet.io/code_reviews/342260?submission_id=433389","plain_title":"Добрый день. Не могу разобраться, в чем ошибка в линтере - 5:31 error Expected to return a value at the end of arrow function consistent-return. ссылка на ревью. https://ru.hexlet.io/codereviews/342260?submissionid=433389 ","creator":{"public_name":"Nock1391","id":321901,"is_tutor":false},"comments":[{"creator":{"public_name":"Stanislav Dzisiak","id":212236,"is_tutor":true},"id":106405,"body":"**Nock1391**, приветствую!\n\nКак отметил Владимир, проблема в отсутствующем возврате из функции. Правило линтера [consistent-return](https://eslint.org/docs/rules/consistent-return) говорит о том, что стрелочная функция или должна во всех случаях иметь явный возврат или не иметь возвратов вообще. В данном случае не необходимости в использовании последнего условия if (num > 1), попробуйте его убрать, как рекомендует Владимир и ошибка должна быть исправлена.","topic_id":49587},{"creator":{"public_name":"Vladimir","id":321511,"is_tutor":false},"id":106349,"body":"линтер ругается, что в конце функции ожидается return, у вас его там нет, последний if не нужен, к этому моменту и так уже num > 1 будет","topic_id":49587}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Переменные, декларативное и императивное программирование","entity_url":null,"active":true}},{"id":17980,"title":"Приветствую) ошибку хочу найти, но не могу вообще,намекните пж)\n```// BEGIN (write your solution here)\nconst smallestDivisor=(n)=>\n{\n let x=2;\n let y=1;\n while (x!=0)\n {\n x=n%y;\n y=y+1;\n }\n return y;\n}\nsmallestDivisor(15)\n// END","plain_title":"Приветствую) ошибку хочу найти, но не могу вообще,намекните пж) ```// BEGIN (write your solution here) const smallestDivisor=(n)=> { let x=2; let y=1; while (x!=0) { x=n%y; y=y+1; } return y; } smallestDivisor(15) // END ","creator":{"public_name":"","id":184660,"is_tutor":false},"comments":[{"creator":{"public_name":"Александр О.","id":61806,"is_tutor":false},"id":37988,"body":"Добрый день! Не могли бы вы немного отформатировать ваш код - расставить отступы (код тела функции должен иметь отступ, и код тела цикла также должен иметь отдельный отступ). Также обращаю внимание, что тройные тики должны быть единственными на строке (код помещается между ними). Вот здесь подробнее примеры форматирования: https://guides.hexlet.io/markdown/#%D0%BA%D0%BE%D0%B4\n\n> ошибку хочу найти, но не могу вообще,намекните пж)\n\nСамый первый намён находитс в выводе тестов: вы его анализировали? Что там написано?","topic_id":17980},{"creator":{"public_name":"Александр О.","id":61806,"is_tutor":false},"id":37998,"body":"> TypeError: (0 , _solution.default) is not a function\n\nОшибка связана с экспортом фукнции - проверьте, вы правильным образом сделали экспорт, в соответствии с заданием?","topic_id":17980},{"creator":{"public_name":"","id":184660,"is_tutor":false},"id":37996,"body":"type error, пишет ошибка типа функции\n TypeError: (0 , _solution.default) is not a function\nнеправильно функцию записал как я понимаю, но не вижу где","topic_id":17980}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Переменные, декларативное и императивное программирование","entity_url":null,"active":true}},{"id":28994,"title":"HELP!!!\nПомогите пожалуйста, никак не могу понять тему, решал предыдущие с помощью ответов преподавателя. Нить утерял с момента вызова функции внутри функции","plain_title":"HELP!!! Помогите пожалуйста, никак не могу понять тему, решал предыдущие с помощью ответов преподавателя. Нить утерял с момента вызова функции внутри функции ","creator":{"public_name":"Pavel Gorbachev","id":232318,"is_tutor":false},"comments":[{"creator":{"public_name":"Сергей К.","id":5174,"is_tutor":false},"id":62622,"body":"Павел, добрый день! Расскажите, пожалуйста, подробнее, что выполняли, с какой проблемой столкнулись?","topic_id":28994}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Переменные, декларативное и императивное программирование","entity_url":null,"active":true}},{"id":22251,"title":"Привет) Помогите, пожалуйста, как выполнить последнюю задачу? Первые три пункта у меня вроде правильные, вот: \n```\n// BEGIN (write your solution here)\nconst smallestDivisor = (num) => {\n let delitel = 2;\n if (num < 1) {\n return NaN;\n }\n\n while (num % delitel === 0) {\n delitel = delitel + 1;\n }\n \n return delitel;\n}\n// END\n\nexport default smallestDivisor;\n```\n\nНо выдает ошибку\n\n```\n 4 | expect(smallestDivisor(-3)).toEqual(NaN);\n 5 | expect(smallestDivisor(0)).toEqual(NaN);\n > 6 | expect(smallestDivisor(1)).toBe(1);\n | ^\n 7 | expect(smallestDivisor(4)).toBe(2);\n 8 | expect(smallestDivisor(121)).toBe(11);\n 9 | expect(smallestDivisor(3)).toBe(3);\n```\nЭто значит, что первые числа у меня получились, а 1 нет. Как раз потому, что я не указал 4 пункт, а вот как его указать я не знаю.","plain_title":"Привет) Помогите, пожалуйста, как выполнить последнюю задачу? Первые три пункта у меня вроде правильные, вот: ``` // BEGIN (write your solution here) const smallestDivisor = (num) => { let delitel = 2; if (num < 1) { return NaN; } while (num % delitel === 0) { delitel = delitel + 1; } return delitel; } // END export default smallestDivisor; ``` Но выдает ошибку 4 | expect(smallestDivisor(-3)).toEqual(NaN); 5 | expect(smallestDivisor(0)).toEqual(NaN); > 6 | expect(smallestDivisor(1)).toBe(1); | ^ 7 | expect(smallestDivisor(4)).toBe(2); 8 | expect(smallestDivisor(121)).toBe(11); 9 | expect(smallestDivisor(3)).toBe(3); Это значит, что первые числа у меня получились, а 1 нет. Как раз потому, что я не указал 4 пункт, а вот как его указать я не знаю. ","creator":{"public_name":"Максим Комаров","id":198417,"is_tutor":false},"comments":[{"creator":{"public_name":"Олег Иванов","id":198165,"is_tutor":false},"id":47371,"body":"Но здесь не получится ни одно число больше нуля. Какое именно условие проверяет этот цикл while, и что он делает в зависимости от [не]выполнения этого условия?","topic_id":22251}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Переменные, декларативное и императивное программирование","entity_url":null,"active":true}},{"id":14365,"title":"```\n// removed\n```\nпочему такая конструкция не срабатывает?","plain_title":"// removed почему такая конструкция не срабатывает? ","creator":{"public_name":"Виталий Караман","id":170097,"is_tutor":false},"comments":[{"creator":{"public_name":"Виталий Караман","id":170097,"is_tutor":false},"id":30161,"body":"вопрос решил","topic_id":14365},{"creator":{"public_name":"Kirill Mokevnin","id":1,"is_tutor":false},"id":30166,"body":"Отлично)","topic_id":14365}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Переменные, декларативное и императивное программирование","entity_url":null,"active":true}},{"id":32231,"title":"Здравствуйте вопрос по тестам: \"Специальный код производит распечатку текста на принтере. В коде используются команды, которые преобразуют текст в специальную форму, отправляют такой текст в принтер при помощи USB-кабеля, разбивают текст на страницы и так далее. К какому типу относится такой код?\" Почему это императивное описание, а не декларативное?","plain_title":"Здравствуйте вопрос по тестам: \"Специальный код производит распечатку текста на принтере. В коде используются команды, которые преобразуют текст в специальную форму, отправляют такой текст в принтер при помощи USB-кабеля, разбивают текст на страницы и так далее. К какому типу относится такой код?\" Почему это императивное описание, а не декларативное? ","creator":{"public_name":"Сергей Волков","id":185486,"is_tutor":false},"comments":[{"creator":{"public_name":"Владислав Родько","id":76372,"is_tutor":false},"id":69969,"body":"**Сергей Волков**, \n\nЗдравствуйте, Сергей. Как было сказано в статье, императивное программирование отвечает на вопрос **КАК** _решить задачу_, в то время как декларативное дает ответ на вопрос **ЧТО** _представляет собой проблема и ожидаемый результат_.\n\nВ вопросе теста рассказывается, **КАК** мы можем распечатать текст на принтере: преобразовать текст в специальную форму, затем отправить его в принтер при помощи USB-кабеля, разбить текст и т.д.\nПоэтому такой тип кода относится к императивному программированию.\n","topic_id":32231}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Переменные, декларативное и императивное программирование","entity_url":null,"active":true}}],"lesson":{"exercise":null,"units":[{"id":1845,"name":"theory","url":"/courses/introduction_to_programming/lessons/while/theory_unit"}],"links":[{"id":427077,"name":"Iteration on Wikipedia","url":"https://en.wikipedia.org/wiki/Iteration"},{"id":427078,"name":"Fundamentals of Programming: Iteration","url":"https://en.wikibooks.org/wiki/A-level_Computing/AQA/Paper_1/Fundamentals_of_programming/Iteration"},{"id":427079,"name":"Музыка из видео","url":"https://www.bensound.com"}],"ordered_units":[{"id":1845,"name":"theory","url":"/courses/introduction_to_programming/lessons/while/theory_unit"}],"id":898,"slug":"while","state":"approved","name":"Переменные, декларативное и императивное программирование","course_order":110,"goal":"Изучаем новые термины: переменные, циклы и изменяемые данные. Учимся отличать декларативное программирование от императивного.","self_study":null,"theory_video_provider":"youtube","theory_video_uid":"rjbt2ga7Ezk","theory":"## Транскрипт урока\n\nМы уже знакомы со способом называть что-то, используя константы. Например, это константа `pi` со значением `3.14`.\n\n```javascript\nconst pi = 3.14\n```\n\nПосле этой строки, каждый раз, когда мы видим `pi`, мы знаем, что её значение `3.14`. Она называется константой, потому что, ээм, она неизменна, постоянна. После этой строки `pi` всегда будет `3.14`, это никогда не изменится. Именно поэтому по аналогии с бумагой я использую ручку.\n\nЭто может показаться ограничением, но вообще — это довольно хорошее свойство. Изменение того, что мы уже создали — сложная задача. Представьте, что пишете код, используя константу, в значении которой не уверены.\n\nТем не менее, иногда вам может потребоваться изменить уже существующие данные или, другими словами, их значения. Допустим, вы хотите повторить что-то 5 раз. Один способ — выполнять повторы, отсчитывая до пяти, а затем остановиться. Для этого вам потребуется что-нибудь для хранения счётчика этого меняющегося числа. Константа не будет в таком случае работать — она неизменна, вы не можете изменить её значение после того, как уже создали её.\n\nПоэтому в JavaScript и многих других языках программирования существует идея переменной. Можно представить ее в виде такой же бумажки, на которой имя написано ручкой, но значение — карандашом. В любой момент можно заменить значение на другое.\n\nМожно посчитать факториал с помощью переменной вот так:\n\n```javascript\nlet factorial = 1\n\nfactorial = factorial * 2 // 2\nfactorial = factorial * 3 // 6\nfactorial = factorial * 4 // 24\nfactorial = factorial * 5 // 120\n```\n\nСоздать переменную — просто, она выглядит как константа, только вместо `const` мы пишем `let`. Мы позволяем ей быть чем-то и это не навсегда.\n\nЗатем мы изменяем значение `factorial`. Мы бы такого не смогли сделать, если бы `factorial` был константой. Эта строка означает \"изменить значение переменной факториал, на результат умножения факториала на 2\". Теперь JavaScript умножает `factorial` на 2 и хранит этот результат в переменной `factorial`. Раньше `factorial` был 1, а теперь это 2.\n\nМы повторяем это ещё трижды, каждый раз умножая полученное значение на следующее целое число: на 3, на 4 и на 5. Это то, что вы возможно делаете в уме, когда умножаете числа. Вероятно, вы не думали об этом так чётко, но это неплохой способ описания процесса вычисления, если бы вам было нужно объяснить его.\n\nИдея использования счётчика для повторения чего-то множество раз — распространённая в программировании, и большинство языков программирования имеют для этого \"циклы\". Давайте рассмотрим один тип цикла — \"цикл while\". Это блок кода, который повторяется, пока удовлетворяется какое-то условие.\n\nПредставьте фермера, который работает от рассвета до заката. Другими словами, он работает пока солнце в небе. Вы можете записать:\n\n```\nwhile (sun is up) {\n work\n}\n```\n\nКонечно, это не настоящий JavaScript, это просто чтобы показать идею. Эта строка \"work\" будет повторяться снова и снова, пока солнце над горизонтом. Это значит после каждого повторения нам нужно проверять, действительно ли солнце в небе, и остановиться если это не так. Другими словами: проверить — исполнить, проверить — исполнить, и так далее.\n\nВот функция факториала с переменными и циклом вместо рекурсии.\n\n```javascript\nconst factorial = (n) => {\n let counter = 1\n let result = 1\n\n while (counter <= n) {\n result = result * counter\n counter = counter + 1\n }\n\n return result\n}\n```\n\nО-о, что тут происходит? Во-первых, мы создали две переменные: одна для счётчика, чтобы считать от 1 до верхнего предела, а вторая для текущего результата.\n\nЗатем начинается главная часть: цикл while, который повторяется, пока счётчик меньше или равен n — числу, переданному в эту функцию. Код, который повторяется, простой: мы меняем значения наших двух переменных. Текущий результат умножается на счётчик, а счётчик увеличивается на 1.\n\nВ какой-то момент это условие — \"счётчик меньше или равен n\" — станет ложным, цикл больше не будет повторяться, а программа перейдёт к следующему этапу — `return result`. К этому моменту результат станет ответом, потому что за время всех повторов в цикле, результат умножался на 1, затем на 2, 3 и так далее, пока не достиг значения n, каким бы оно ни было.\n\nДавайте посмотрим, что компьютер делает шаг за шагом, когда мы вызываем факториал 3.\n\n1. Взять один аргумент — 3, известный внутри, как `n`\n2. Создать переменную `counter`, установить значение 1\n3. Создать переменную `result`, установить значение 1\n4. Проверить: в счётчике — 1, это меньше или равно `n`, поэтому\n5. Умножить `result` на `counter` и положить ответ — 1 — в `result`\n6. Добавить 1 к `counter` и положить ответ — 2 — в `counter`\n7. Вернуться и проверить: `counter` — 2, это меньше или равно `n`, поэтому\n8. Умножить `result` на `counter` и положить ответ — 2 — в `result`\n9. Добавить 1 к `counter` и положить ответ — 3 — в `counter`\n10. Вернуться и проверить: `counter` — 3, это меньше или равно `n`, поэтому\n11. Умножить `result` на `counter` и положить ответ — 6 — в `result`\n12. Добавить 1 к `counter` и положить ответ — 4 — в `counter`\n13. Вернуться и проверить: `counter` — 4, это не меньше и не равно `n`, поэтому остановить повтор и перейти к следующей строке\n14. Вернуть `result` — 6\n\nКомпьютер выполняет такие операции в миллиарды раз быстрее, но по сути это выглядит именно так. Общее название такого вида сформулированных повторений — \"итерация\". Наша программа использует итерацию, чтобы рассчитать факториал.\n\nВ прошлый раз мы рассматривали итеративный процесс с рекурсией, а в этот — итеративный процесс без рекурсии.\n\nОба используют технику итерации, но с рекурсивными вызовами нам не нужно менять значения, мы просто передаём новые значения в следующий вызов функции. А эта функция факториала не имеет рекурсивных вызовов вообще, поэтому все трансформации должны происходить внутри единственного экземпляра, единственной функциональной коробки. У нас нет выбора, кроме как менять значения содержимого.\n\nСтиль программирования, который вы видели в предыдущих уроках, называется \"декларативным\". Сегодняшний стиль, с изменением значений, называется \"императивным\".\n\nСравните рекурсивный и нерекурсивный факториалы:\n\n```javascript\nconst recursiveFactorial = (n) => {\n if (n === 1) {\n return 1\n }\n return n * recursiveFactorial(n - 1)\n}\n\nconst factorial = (n) => {\n let counter = 1\n let result = 1\n\n while (counter <= n) {\n result = result * counter\n counter = counter + 1\n }\n\n return result\n}\n```\n\nЭта рекурсивная функция — декларативная — она как описание факториала. Она объясняет, что такое факториал.\n\nЭто нерекурсивная итеративная функция, и она императивная — она описывает, что делать, чтобы найти факториал.\n\nСлово декларативный происходит от латинского \"clarare\" — *разъяснять, заявлять, делать объявление*. Вы разъясняете: я хочу, чтобы факториал n был n умножить на факториал n-1.\n\nСлово императивный происходит от латинского \"imperare\", что значит \"*командовать*\". Вы приказываете чётко передвигаться по шагам — умножать это на это, пока идёт отсчёт и запоминать какие-то числа.\n\nДекларативное — это что. Императивное — это как.\n\nПисать декларативный код, в целом, лучший подход. Ваш код будет легче читать, понимать и делать что-то новое опираясь на него. Некоторые языки провоцируют вас использовать тот или иной подход, а некоторые вообще не оставляют выбора.\n\nНо в итоге вам нужно будет научиться оценивать, когда императивный подход принесет больше проблем чем решений.\n\nСледить за изменениями – сложно, и буквально несколько переменных могут сделать систему очень сложной для понимания.\n\nОт изменения состояния появляется гора багов, а **оператор присваивания** (**assignment statements**), который создает изменения, часто является причиной всего зла во вселенной.\n\n## Дополнение к уроку\n\n### var vs let\n\nКроме `let` существует другой способ определения переменных: `var a = 5`. Этот способ был единственным до появления стандарта ES6, но в современном JavaScript он является устаревшим, и `let` полностью заменил его.\n\n`let` и `var` по-разному влияют на видимость переменной, и использование `var` сегодня нежелательно. `let` был создан как более правильная альтернатива старому способу.\n\n### Отладка: Как найти и исправить ошибки\n\nНаделать ошибок очень легко, когда приходится справляться с переменными, изменять их, отслеживать и всякое такое. Особенно в зацикленном процессе. Прекрасный способ разобраться с тем, что происходит — использовать простейшую технику для отладки — `console.log`. Вспомните, эта функция выводит в консоль то, что ей передают.\n\nНапример, я пытаюсь разобраться, что происходит внутри цикла while:\n\n```javascript\nwhile (counter <= n) {\n result = result * result\n counter = counter + 1\n}\n```\n\nДобавлю сюда console.log:\n\n```javascript\nwhile (counter <= n) {\n result = result * result\n counter = counter + 1\n console.log(result)\n}\n```\n\nТеперь, каждый раз, когда повторяется этот блок кода, переменная `result` будет выводиться на экран. Давайте посмотрим:\n\n```bash\n1\n1\n1\n```\n\n*(Я запускаю функцию с `n` равным 3)*\n\nВ каждом шаге `result` — это 1. Не верно — `result` должен возрастать на каждом шаге… Ок, значит вероятная проблема, в строке, где `result` меняется. Так и есть! У меня `result = result * result`, а мне нужно умножить `result` на `counter`, а не на `result`.\n\n```bash\n1\n2\n6\n```\n\nТеперь всё работает! Теперь я вижу шаги и последний шаг выдал верный ответ: 3! это 6. Используйте `console.log` абсолютно везде. Это ваш лучший друг :-)\n\n### Бесконечные циклы\n\nПоскольку цикл while только проверяет состояние, мы можем создать бесконечные циклы, если сделаем состояние всегда истинным.\n\n```javascript\nwhile (10 > 5) {\n console.log('Ten is still larger than 5')\n}\n```\n\nЭтот код будет выводить на экран \"Десять всё ещё больше чем 5\" пока не сгорит вселенная или пока вы не закроете программу, ну или пока компьютер не израсходует всю свою память — что бы ни случилось первым. Поскольку состояние `10 > 5` всегда истинно.\n\nЕсть еще более простой способ сделать бесконечный цикл — `while (true) { ... }`. При этом `true` всегда истинный.\n\nИногда ваши циклы будут бесконечными, даже если вы этого не планировали. Это общая проблема, и она указывает только на то, что внутри цикла вы забыли изменить проверяемую деталь. Например, если я удалю строку `counter = counter + 1` из цикла в сегодняшнем уроке:\n\n```javascript\nwhile (counter <= n) {\n result = result * result\n}\n```\n\n… у меня получится бесконечный цикл: counter никогда не меняется, поэтому если `counter <= n`, условие всегда будет истинно.\n\n## Выводы\n\n**Переменные** подобны константам, но вы можете изменить их значения в любой момент.\n\n```javascript\nlet age = 21\n\nage = 22 // now age is 22\nage = age + 10 // now age is 32\n```\n\n**Циклы** — это повторяющиеся блоки кода. **Цикл while** — это блок, повторяющийся пока какое-то *состояние* истинно.\n\n\n```javascript\nwhile (condition) {\n do_stuff\n}\n```\n\nВот факториал функции с циклом while:\n\n```javascript\nconst factorial = (n) => {\n let counter = 1\n let result = 1\n\n while (counter <= n) {\n result = result * counter\n counter = counter + 1\n }\n\n return result\n}\n```\n\nИдея: сделать `counter` = 1, затем умножать `result` на `counter` повторно, пока идёт отсчёт до `n` (число, передаваемое функции). Когда `counter` станет больше, чем `n` — остановиться. К тому моменту `result` будет ответом.\n\nЭто **итерация** — сформулированное повторение кода. Разные языки по-разному выполняют итерацию. Цикл while — это один из способов, который предлагает JavaScript.\n\n### Декларативное vs. императивное программирование\n\nСравните рекурсивный факториал (из 9 урока) и нерекурсивный факториал (из сегодняшнего):\n\n```javascript\nconst recursiveFactorial = (n) => {\n if (n === 1) {\n return 1\n }\n return n * recursiveFactorial(n - 1)\n}\n\nconst factorial = (n) => {\n let counter = 1\n let result = 1\n\n while (counter <= n) {\n result = result * counter\n counter = counter + 1\n }\n\n return result\n}\n```\n\nЭта рекурсивная функция — **декларативная** — она как бы определение (трактование, характеристика) факториала. Она декларирует, что такое факториал.\n\nЭта нерекурсивная итеративная функция — **императивная** — описание того, что нужно делать, чтобы найти факториал.\n\nСлово декларативный происходит от латинского \"clarare\" — *разъяснять, заявлять, делать объявление*. Вы разъясняете: я хочу, чтобы факториал n был n раз факториалом n-1.\n\nСлово императивный происходит от латинского \"imperare\", что значит \"*командовать*\". Вы приказываете чётко передвигаться по шагам — умножать это на это, пока идёт отсчёт и запоминаются какие-то числа.\n\n>Декларативное — это что. Императивное — это как.\n\nПисать декларативный код, в целом, лучший выбор. Ваш код будет легче читать, понимать и делать что-то новое опираясь на него. Но иногда у вас нет выбора.\n\nОт изменения состояния* появляется гора багов, а **инструкции (операторы) присваивания** (**assignment statements**), которые создают изменения, часто являются коренными причинами всего зла во вселенной.\n\nПоэтому, когда дело доходит до инструкций присваивания, **действуйте осторожно**.\n"},"lessonMember":null,"courseMember":null,"course":{"start_lesson":{"exercise":null,"units":[{"id":1801,"name":"theory","url":"/courses/introduction_to_programming/lessons/intro/theory_unit"}],"links":[{"id":427047,"name":"Inside your computer - Bettina Bair","url":"https://www.youtube.com/watch?v=AkFi90lZmXA"},{"id":427048,"name":"Punch Card Programming - Computerphile","url":"https://www.youtube.com/watch?v=KG2M4ttzBnY"},{"id":427049,"name":"The Future of Computer Intelligence Is Everything but Artificial","url":"https://www.wired.com/2014/06/the-future-of-computer-intelligence-is-everything-but-artificial/"}],"ordered_units":[{"id":1801,"name":"theory","url":"/courses/introduction_to_programming/lessons/intro/theory_unit"}],"id":876,"slug":"intro","state":"approved","name":"Что такое компьютер?","course_order":10,"goal":"Первый урок посвящен знакомству с Тотой – главным персонажем Хекслета. Вместе с нашим героем отвечаем на простые, но важные вопросы: Что такое компьютер? Умный ли он? Говорит ли он на языке программирования?","self_study":null,"theory_video_provider":"youtube","theory_video_uid":"rrRZZ_3licM","theory":"## Транскрипт урока\n\nЭто Тота.\n\nТота - пещерный человек.\n\nОднажды он шёл по лесу и неожиданно перед ним из ниоткуда возник большой, шумный сферический объект, поблескивая и мерцая.\n\n\"Прямо как в Терминаторе\", - сказал бы Тота, если бы видел фильм Терминатор.\n\nОбъект быстро исчез, оставив на траве чёрный дымящийся ящик.\n\nТоту захватило любопытство, и он ждал, пока дым рассеется, чтобы изучить непонятную штуку.\n\nЭто была тяжёлая коробка с двумя кнопками сбоку, на одной из кнопок было написано Х, на другой О. Наверху была щель, а сбоку торчал рычаг. Как настоящий пещерный человек, Тота пытался щупать её, пинать, нюхать и валять по земле. Ящик определённо не был живым, но кнопки интриговали его.\n\nТота обнаружил интересное свойство: если нажать Х и О последовательно, а потом опустить рычаг, то на короткое время вначале загорится кнопка О, а потом Х.\n\nЯ вам говорил, что Тота был невероятно умным? Самым умным в своей пещере.\n\nОн решил нажать кнопки в том порядке, в котором они загорались, а потом снова опустить рычаг.\n\nТеперь отклик был другой — кнопки загорелись по новой схеме. Когда Тота ввел в коробку последнюю схему, ящик издал звук и изверг молнию, безумно напугал Тоту и поджёг стоящие впереди деревья. \n\nТеперь у Тоты было что-то подобное оружию. Он убил им много животных и часто наслаждался горячей пищей, сидя у костра.\n\nВскоре он открыл другие схемы: одна из них производила ненавистный Тоте звук, после другой выплевывался лист с какими-то пометками, а некоторые комбинации вообще ни к чему не приводили.\n\nОднажды Тота обнаружил ещё более продвинутую особенность этого прибора. Он хотел снова сделать костёр, но вместо того, чтобы просто нажать на рычаг один раз, он нажал и подержал его. После того, как он отпустил его несколько моментов спустя, пламени не возникло, но и Х и О стали мигать. Он отчаянно нажал О и мигание прекратилось. С того момента нажатия О и опускания рычага было достаточно, чтобы произвести огонь, намного проще и быстрее, чем раньше!\n\nОн понял, что натренировал этого зверя, точно так же, как однажды натренировал волчонка.\n\nТак что это за штука?\n\nКонечно, Тота называет её Бум-вум, но мы можем придумать что-то получше. Изначально можно подумать, что это какое-то чрезмерно усложнённое оружие. Но оно производит и другие странные вещи, вроде музыки... и даже печати. Оно не похоже на бытовой прибор, хотя, некоторые стиральные машины намного сложнее в эксплуатации.\n\nДавайте начнём с кнопок. Похоже машина \"понимает\" определённые комбинации и не понимает другие. Мы не знаем назначения кнопок и комбинации, поэтому я хочу назвать это \"кодом\", вроде \"я понятия не имею что это, но, наверное, это что-то значит\". Некоторые коды работают, некоторые — нет, так же как в речи некоторые звуки означают что-то, а другие — нет. \"Язык\", кажется, подходящее слово. Эта машина понимает определенный язык кодов.\n\nХорошо, как тогда мы назовём эту машину? Пониматель языка кода? \"Понимать\" звучит важно, но основная задача машины не в том, чтобы понимать, а в том, чтобы выдавать какой-то результат. Она понимает код - \"огненная вспышка\" и немедленно эту вспышку создаёт. Поэтому, можно назвать её... выполнитель языка кода? Она выполняет некоторые действия. \n\nТот, кто послал эту штуку из будущего в каменный век, возможно называл её иначе, но мы, определённо, называем эту машину компьютером. Именно такие машины принимают код и выполняют какие-то действия.\n\nВам может показаться, что это ужасный компьютер с ужасным кодом. Сегодня у нас есть магические устройства с фантастическими особенностями и языки программирования с кодами, которые легко читать, вроде этого:\n\n```javascript\nconst factorial = (n) => {\n const iter = (current, acc) => {\n if (current === 0) {\n return acc\n }\n return iter(current - 1, acc * current)\n }\n\n return iter(n, 1)\n}\n```\n\nКстати, в конце курса, вы сможете писать и понимать подобный код с лёгкостью.\n\nДа, современные компьютеры отличаются от тех, что были раньше. Но... не слишком. Мы еще не исследовали эту машину досконально, но, поверьте - по сути они одинаковы. Так же как это... сильно отличается от этого... оба объекта работают по одинаковому принципу и выполняют одинаковую функцию, в разной степени.\n\nПродолжая рассматривать эту странную машину, мы можем понять кое-что важное в компьютерах в целом: \n\nПервое: компьютер понимает определённый, строгий язык. Случайные нажатия не приводят к результату, работают только конкретные комбинации. Крошечная ошибка в схеме ломает всё. \n\nИ второе: компьютеры по-настоящему тупы.\n\nВозможно, вы подумаете, что последнее высказывание касается этого конкретного компьютера, странного и маломощного, но я говорю о компьютерах вообще. Они очень мощные, но одновременно тупые. Не сомневайтесь - всё, что они делают, это выполняют действия, которые мы им задаём. Никакой магии. Но, безусловно, для Тоты - это магия, так же как современные устройства кажутся нам магическими, если только мы не изучим программирование. К счастью, именно этим мы и собираемся заняться в этом курсе.\n\n## Выводы\n\n- Компьютер принимает код и выполняет действия\n- Компьютер понимает определённый язык кодов:\n - Некоторые коды работают\n - Некоторые коды не работают\n - В коде жёсткие правила \n- Компьютеры по существу не такие умные, как люди, они только выполняют наши указания. А указания для компьютеров выражаются в виде кода.\n- Все компьютеры фундаментально одинаковы. Примитивный, старый, маломощный компьютер и современный ноутбук используют одинаковые принципы и способны на одинаковые операции, в разной степени.\n"},"id":143,"slug":"introduction_to_programming","challenges_count":0,"name":"Введение в программирование","allow_indexing":true,"state":"approved","course_state":"finished","pricing_type":"free","description":"В этом курсе вы изучите основы программирования. Вы узнаете больше о языках программирования, их синтаксисе и правильном выборе языка для обучения. В итоге вы научитесь использовать функции, условия и циклы, а также напишите свои первые программы на JavaScript. Знания из этого курса пригодятся, если вы решите заниматься программированием и познакомиться с ключевыми принципами написания хорошего кода.","kind":"sandbox","updated_at":"2026-02-06T11:25:43.725Z","language":"javascript","duration_cache":18000,"skills":["Использовать основные языковые конструкции: условия, циклы, функции и другие","Разделять код на модули для повторного использования и отсутствия конфликта имён","Понимать ключевые концепции для написания хорошего кода, такие как чистота и детерминированность"],"keywords":["основы javascript","чистый код","алгоритмы","логика"],"lessons_count":20,"cover":"https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MTI1NzIsInB1ciI6ImJsb2JfaWQifX0=--3444a6a2b32ba0a1b370387ae75d0c63f10ad54f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJwbmciLCJyZXNpemVfdG9fZmlsbCI6WzYwMCw0MDBdfSwicHVyIjoidmFyaWF0aW9uIn19--6067466c2912ca31a17eddee04b8cf2a38c6ad17/image.png"},"recommendedLandings":[],"lessonMemberUnit":null,"accessToLearnUnitExists":true,"accessToCourseExists":true},"url":"/courses/introduction_to_programming/lessons/while/theory_unit","version":"0b0c6d4ebbd40fd58630a0dd89cc25544ccdf24e","encryptHistory":false,"clearHistory":false}"><style data-mantine-styles="true">:root, :host{--mantine-font-family: Arial, sans-serif;--mantine-font-family-headings: Arial, sans-serif;--mantine-heading-font-weight: normal;--mantine-radius-default: 0rem;--mantine-primary-color-filled: var(--mantine-color-indigo-filled);--mantine-primary-color-filled-hover: var(--mantine-color-indigo-filled-hover);--mantine-primary-color-light: var(--mantine-color-indigo-light);--mantine-primary-color-light-hover: var(--mantine-color-indigo-light-hover);--mantine-primary-color-light-color: var(--mantine-color-indigo-light-color);--mantine-spacing-xxl: calc(4rem * var(--mantine-scale));--mantine-font-size-xs: 12px;--mantine-font-size-sm: 14px;--mantine-font-size-md: 16px;--mantine-font-size-lg: clamp(16.0000px, calc(15.2727px + 0.2273vw), 18.0000px);--mantine-font-size-xl: clamp(16.0000px, calc(14.5455px + 0.4545vw), 20.0000px);--mantine-font-size-display-3: clamp(32.0000px, calc(26.1818px + 1.8182vw), 48.0000px);--mantine-font-size-display-2: clamp(36.0000px, calc(25.8182px + 3.1818vw), 64.0000px);--mantine-font-size-display-1: clamp(40.0000px, calc(25.4545px + 4.5455vw), 80.0000px);--mantine-font-size-h1: clamp(28.0000px, calc(23.6364px + 1.3636vw), 40.0000px);--mantine-font-size-h2: clamp(24.0000px, calc(21.0909px + 0.9091vw), 32.0000px);--mantine-font-size-h3: clamp(20.0000px, calc(17.0909px + 0.9091vw), 28.0000px);--mantine-font-size-h4: clamp(16.0000px, calc(13.0909px + 0.9091vw), 24.0000px);--mantine-font-size-h5: clamp(16.0000px, calc(14.5455px + 0.4545vw), 20.0000px);--mantine-font-size-h6: 1rem;--mantine-primary-color-0: var(--mantine-color-indigo-0);--mantine-primary-color-1: var(--mantine-color-indigo-1);--mantine-primary-color-2: var(--mantine-color-indigo-2);--mantine-primary-color-3: var(--mantine-color-indigo-3);--mantine-primary-color-4: var(--mantine-color-indigo-4);--mantine-primary-color-5: var(--mantine-color-indigo-5);--mantine-primary-color-6: var(--mantine-color-indigo-6);--mantine-primary-color-7: var(--mantine-color-indigo-7);--mantine-primary-color-8: var(--mantine-color-indigo-8);--mantine-primary-color-9: var(--mantine-color-indigo-9);--mantine-color-red-0: #ffeaea;--mantine-color-red-1: #fed4d4;--mantine-color-red-2: #f4a7a8;--mantine-color-red-3: #ec7878;--mantine-color-red-4: #e55050;--mantine-color-red-5: #e03131;--mantine-color-red-6: #e02829;--mantine-color-red-7: #c71a1c;--mantine-color-red-8: #b21218;--mantine-color-red-9: #9c0411;--mantine-color-violet-0: #fce9ff;--mantine-color-violet-1: #f1cfff;--mantine-color-violet-2: #e09bff;--mantine-color-violet-3: #d16fff;--mantine-color-violet-4: #be37fe;--mantine-color-violet-5: #b51afe;--mantine-color-violet-6: #b009ff;--mantine-color-violet-7: #9b00e4;--mantine-color-violet-8: #8a00cc;--mantine-color-violet-9: #7800b3;--mantine-color-indigo-0: #edecff;--mantine-color-indigo-1: #d6d5fe;--mantine-color-indigo-2: #aaa9f4;--mantine-color-indigo-3: #7b79eb;--mantine-color-indigo-4: #5451e4;--mantine-color-indigo-5: #3b37e0;--mantine-color-indigo-6: #2d2adf;--mantine-color-indigo-7: #1f1ec7;--mantine-color-indigo-8: #1819b2;--mantine-color-indigo-9: #0c149e;--mantine-color-cyan-0: #dffdff;--mantine-color-cyan-1: #caf5ff;--mantine-color-cyan-2: #99e8ff;--mantine-color-cyan-3: #64daff;--mantine-color-cyan-4: #3ccffe;--mantine-color-cyan-5: #24c8fe;--mantine-color-cyan-6: #00c2ff;--mantine-color-cyan-7: #00ade4;--mantine-color-cyan-8: #009acd;--mantine-color-cyan-9: #0085b5;--mantine-color-green-0: #e9fdec;--mantine-color-green-1: #d7f6dc;--mantine-color-green-2: #b0eab9;--mantine-color-green-3: #86df94;--mantine-color-green-4: #62d574;--mantine-color-green-5: #4ccf5f;--mantine-color-green-6: #3fcc54;--mantine-color-green-7: #2fb344;--mantine-color-green-8: #25a03b;--mantine-color-green-9: #138a2e;--mantine-color-yellow-0: #fff7e2;--mantine-color-yellow-1: #ffeecd;--mantine-color-yellow-2: #ffdc9c;--mantine-color-yellow-3: #ffc966;--mantine-color-yellow-4: #feb93a;--mantine-color-yellow-5: #feae1e;--mantine-color-yellow-6: #ffa90f;--mantine-color-yellow-8: #ca8200;--mantine-color-yellow-9: #af7000;--mantine-h1-font-size: clamp(28.0000px, calc(23.6364px + 1.3636vw), 40.0000px);--mantine-h1-font-weight: normal;--mantine-h2-font-size: clamp(24.0000px, calc(21.0909px + 0.9091vw), 32.0000px);--mantine-h2-font-weight: normal;--mantine-h3-font-size: clamp(20.0000px, calc(17.0909px + 0.9091vw), 28.0000px);--mantine-h3-font-weight: normal;--mantine-h4-font-size: clamp(16.0000px, calc(13.0909px + 0.9091vw), 24.0000px);--mantine-h4-font-weight: normal;--mantine-h5-font-size: clamp(16.0000px, calc(14.5455px + 0.4545vw), 20.0000px);--mantine-h5-font-weight: normal;--mantine-h6-font-size: 1rem;--mantine-h6-font-weight: normal;}
:root[data-mantine-color-scheme="dark"], :host([data-mantine-color-scheme="dark"]){--mantine-color-anchor: var(--mantine-color-text);--mantine-color-dimmed: #495057;--mantine-color-dark-filled: var(--mantine-color-dark-5);--mantine-color-dark-filled-hover: var(--mantine-color-dark-6);--mantine-color-dark-light: rgba(105, 105, 105, 0.15);--mantine-color-dark-light-hover: rgba(105, 105, 105, 0.2);--mantine-color-dark-light-color: var(--mantine-color-dark-0);--mantine-color-dark-outline: var(--mantine-color-dark-1);--mantine-color-dark-outline-hover: rgba(184, 184, 184, 0.05);--mantine-color-gray-filled: var(--mantine-color-gray-5);--mantine-color-gray-filled-hover: var(--mantine-color-gray-6);--mantine-color-gray-light: rgba(222, 226, 230, 0.15);--mantine-color-gray-light-hover: rgba(222, 226, 230, 0.2);--mantine-color-gray-light-color: var(--mantine-color-gray-0);--mantine-color-gray-outline: var(--mantine-color-gray-1);--mantine-color-gray-outline-hover: rgba(241, 243, 245, 0.05);--mantine-color-red-filled: var(--mantine-color-red-5);--mantine-color-red-filled-hover: var(--mantine-color-red-6);--mantine-color-red-light: rgba(236, 120, 120, 0.15);--mantine-color-red-light-hover: rgba(236, 120, 120, 0.2);--mantine-color-red-light-color: var(--mantine-color-red-0);--mantine-color-red-outline: var(--mantine-color-red-1);--mantine-color-red-outline-hover: rgba(254, 212, 212, 0.05);--mantine-color-pink-filled: var(--mantine-color-pink-5);--mantine-color-pink-filled-hover: var(--mantine-color-pink-6);--mantine-color-pink-light: rgba(250, 162, 193, 0.15);--mantine-color-pink-light-hover: rgba(250, 162, 193, 0.2);--mantine-color-pink-light-color: var(--mantine-color-pink-0);--mantine-color-pink-outline: var(--mantine-color-pink-1);--mantine-color-pink-outline-hover: rgba(255, 222, 235, 0.05);--mantine-color-grape-filled: var(--mantine-color-grape-5);--mantine-color-grape-filled-hover: var(--mantine-color-grape-6);--mantine-color-grape-light: rgba(229, 153, 247, 0.15);--mantine-color-grape-light-hover: rgba(229, 153, 247, 0.2);--mantine-color-grape-light-color: var(--mantine-color-grape-0);--mantine-color-grape-outline: var(--mantine-color-grape-1);--mantine-color-grape-outline-hover: rgba(243, 217, 250, 0.05);--mantine-color-violet-filled: var(--mantine-color-violet-5);--mantine-color-violet-filled-hover: var(--mantine-color-violet-6);--mantine-color-violet-light: rgba(209, 111, 255, 0.15);--mantine-color-violet-light-hover: rgba(209, 111, 255, 0.2);--mantine-color-violet-light-color: var(--mantine-color-violet-0);--mantine-color-violet-outline: var(--mantine-color-violet-1);--mantine-color-violet-outline-hover: rgba(241, 207, 255, 0.05);--mantine-color-indigo-filled: var(--mantine-color-indigo-5);--mantine-color-indigo-filled-hover: var(--mantine-color-indigo-6);--mantine-color-indigo-light: rgba(123, 121, 235, 0.15);--mantine-color-indigo-light-hover: rgba(123, 121, 235, 0.2);--mantine-color-indigo-light-color: var(--mantine-color-indigo-0);--mantine-color-indigo-outline: var(--mantine-color-indigo-1);--mantine-color-indigo-outline-hover: rgba(214, 213, 254, 0.05);--mantine-color-blue-filled: var(--mantine-color-blue-5);--mantine-color-blue-filled-hover: var(--mantine-color-blue-6);--mantine-color-blue-light: rgba(116, 192, 252, 0.15);--mantine-color-blue-light-hover: rgba(116, 192, 252, 0.2);--mantine-color-blue-light-color: var(--mantine-color-blue-0);--mantine-color-blue-outline: var(--mantine-color-blue-1);--mantine-color-blue-outline-hover: rgba(208, 235, 255, 0.05);--mantine-color-cyan-filled: var(--mantine-color-cyan-5);--mantine-color-cyan-filled-hover: var(--mantine-color-cyan-6);--mantine-color-cyan-light: rgba(100, 218, 255, 0.15);--mantine-color-cyan-light-hover: rgba(100, 218, 255, 0.2);--mantine-color-cyan-light-color: var(--mantine-color-cyan-0);--mantine-color-cyan-outline: var(--mantine-color-cyan-1);--mantine-color-cyan-outline-hover: rgba(202, 245, 255, 0.05);--mantine-color-teal-filled: var(--mantine-color-teal-5);--mantine-color-teal-filled-hover: var(--mantine-color-teal-6);--mantine-color-teal-light: rgba(99, 230, 190, 0.15);--mantine-color-teal-light-hover: rgba(99, 230, 190, 0.2);--mantine-color-teal-light-color: var(--mantine-color-teal-0);--mantine-color-teal-outline: var(--mantine-color-teal-1);--mantine-color-teal-outline-hover: rgba(195, 250, 232, 0.05);--mantine-color-green-filled: var(--mantine-color-green-5);--mantine-color-green-filled-hover: var(--mantine-color-green-6);--mantine-color-green-light: rgba(134, 223, 148, 0.15);--mantine-color-green-light-hover: rgba(134, 223, 148, 0.2);--mantine-color-green-light-color: var(--mantine-color-green-0);--mantine-color-green-outline: var(--mantine-color-green-1);--mantine-color-green-outline-hover: rgba(215, 246, 220, 0.05);--mantine-color-lime-filled: var(--mantine-color-lime-5);--mantine-color-lime-filled-hover: var(--mantine-color-lime-6);--mantine-color-lime-light: rgba(192, 235, 117, 0.15);--mantine-color-lime-light-hover: rgba(192, 235, 117, 0.2);--mantine-color-lime-light-color: var(--mantine-color-lime-0);--mantine-color-lime-outline: var(--mantine-color-lime-1);--mantine-color-lime-outline-hover: rgba(233, 250, 200, 0.05);--mantine-color-yellow-filled: var(--mantine-color-yellow-5);--mantine-color-yellow-filled-hover: var(--mantine-color-yellow-6);--mantine-color-yellow-light: rgba(255, 201, 102, 0.15);--mantine-color-yellow-light-hover: rgba(255, 201, 102, 0.2);--mantine-color-yellow-light-color: var(--mantine-color-yellow-0);--mantine-color-yellow-outline: var(--mantine-color-yellow-1);--mantine-color-yellow-outline-hover: rgba(255, 238, 205, 0.05);--mantine-color-orange-filled: var(--mantine-color-orange-5);--mantine-color-orange-filled-hover: var(--mantine-color-orange-6);--mantine-color-orange-light: rgba(255, 192, 120, 0.15);--mantine-color-orange-light-hover: rgba(255, 192, 120, 0.2);--mantine-color-orange-light-color: var(--mantine-color-orange-0);--mantine-color-orange-outline: var(--mantine-color-orange-1);--mantine-color-orange-outline-hover: rgba(255, 232, 204, 0.05);--app-cta-gradient: linear-gradient(90deg, var(--mantine-color-blue-9) 0%, var(--mantine-color-cyan-7) 100%);--app-color-surface: #2e2e2e;}
:root[data-mantine-color-scheme="light"], :host([data-mantine-color-scheme="light"]){--mantine-color-anchor: var(--mantine-color-text);--mantine-color-dimmed: #495057;--mantine-color-red-light: rgba(224, 40, 41, 0.1);--mantine-color-red-light-hover: rgba(224, 40, 41, 0.12);--mantine-color-red-outline-hover: rgba(224, 40, 41, 0.05);--mantine-color-violet-light: rgba(176, 9, 255, 0.1);--mantine-color-violet-light-hover: rgba(176, 9, 255, 0.12);--mantine-color-violet-outline-hover: rgba(176, 9, 255, 0.05);--mantine-color-indigo-light: rgba(45, 42, 223, 0.1);--mantine-color-indigo-light-hover: rgba(45, 42, 223, 0.12);--mantine-color-indigo-outline-hover: rgba(45, 42, 223, 0.05);--mantine-color-cyan-light: rgba(0, 194, 255, 0.1);--mantine-color-cyan-light-hover: rgba(0, 194, 255, 0.12);--mantine-color-cyan-outline-hover: rgba(0, 194, 255, 0.05);--mantine-color-green-light: rgba(63, 204, 84, 0.1);--mantine-color-green-light-hover: rgba(63, 204, 84, 0.12);--mantine-color-green-outline-hover: rgba(63, 204, 84, 0.05);--mantine-color-yellow-light: rgba(255, 169, 15, 0.1);--mantine-color-yellow-light-hover: rgba(255, 169, 15, 0.12);--mantine-color-yellow-outline-hover: rgba(255, 169, 15, 0.05);--app-color-surface: #f1f3f5;--app-cta-gradient: linear-gradient(90deg, var(--mantine-color-blue-filled) 0%, var(--mantine-color-cyan-5) 100%);}</style><style data-mantine-styles="classes">@media (max-width: 35.99375em) {.mantine-visible-from-xs {display: none !important;}}@media (min-width: 36em) {.mantine-hidden-from-xs {display: none !important;}}@media (max-width: 47.99375em) {.mantine-visible-from-sm {display: none !important;}}@media (min-width: 48em) {.mantine-hidden-from-sm {display: none !important;}}@media (max-width: 61.99375em) {.mantine-visible-from-md {display: none !important;}}@media (min-width: 62em) {.mantine-hidden-from-md {display: none !important;}}@media (max-width: 74.99375em) {.mantine-visible-from-lg {display: none !important;}}@media (min-width: 75em) {.mantine-hidden-from-lg {display: none !important;}}@media (max-width: 87.99375em) {.mantine-visible-from-xl {display: none !important;}}@media (min-width: 88em) {.mantine-hidden-from-xl {display: none !important;}}</style><div style="position:absolute;top:0rem" class=""></div><div style="max-width:var(--container-size-xl);height:100%;min-height:0rem" class=""><style data-mantine-styles="inline">.__m__-_R_5ub_{--grid-gutter:0rem;}</style><div style="height:100%;min-height:0rem" class="m_410352e9 mantine-Grid-root __m__-_R_5ub_"><div class="m_dee7bd2f mantine-Grid-inner" style="height:100%"><style data-mantine-styles="inline">.__m__-_R_rdub_{--col-flex-grow:auto;--col-flex-basis:91.66666666666667%;--col-max-width:91.66666666666667%;}@media(min-width: 48em){.__m__-_R_rdub_{--col-flex-grow:auto;--col-flex-basis:83.33333333333334%;--col-max-width:83.33333333333334%;}}</style><div style="min-width:0rem;height:100%;min-height:0rem;display:flex" class="m_96bdd299 mantine-Grid-col __m__-_R_rdub_"><style data-mantine-styles="inline">.__m__-_R_6qrdub_{margin-top:0rem;padding-inline:var(--mantine-spacing-xs);width:100%;}@media(min-width: 48em){.__m__-_R_6qrdub_{margin-top:var(--mantine-spacing-xl);width:80%;}}@media(min-width: 62em){.__m__-_R_6qrdub_{padding-inline:var(--mantine-spacing-xl);}}</style><div style="margin-inline:auto;max-width:var(--mantine-breakpoint-xl)" class="__m__-_R_6qrdub_"><div style="color:var(--mantine-color-dimmed)" class="m_4451eb3a mantine-Center-root" data-inline="true"><div style="--ti-size:var(--ti-size-xs);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;margin-inline-end:calc(0.125rem * var(--mantine-scale));color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="xs"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-lock "><path d="M5 13a2 2 0 0 1 2 -2h10a2 2 0 0 1 2 2v6a2 2 0 0 1 -2 2h-10a2 2 0 0 1 -2 -2v-6"></path><path d="M11 16a1 1 0 1 0 2 0a1 1 0 0 0 -2 0"></path><path d="M8 11v-4a4 4 0 1 1 8 0v4"></path></svg></div><p style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Введение в программирование</p></div><h1 style="--title-fw:var(--mantine-h1-font-weight);--title-lh:var(--mantine-h1-line-height);--title-fz:var(--mantine-h1-font-size);margin-bottom:var(--mantine-spacing-xl)" class="m_8a5d1357 mantine-Title-root" data-order="1">Теория: Переменные, декларативное и императивное программирование</h1><script type="application/ld+json">{"@context":"https://schema.org","@type":"LearningResource","name":"Переменные, декларативное и императивное программирование","inLanguage":"ru","isPartOf":{"@type":"LearningResource","name":"Введение в программирование"},"isAccessibleForFree":"False","hasPart":{"@type":"WebPageElement","isAccessibleForFree":"False","cssSelector":".paywalled"}}</script><div class=""><div style="--alert-color:var(--mantine-color-indigo-light-color);margin-bottom:var(--mantine-spacing-lg);font-size:var(--mantine-font-size-lg)" class="m_66836ed3 mantine-Alert-root" id="mantine-_R_remqrdub_" role="alert" aria-describedby="mantine-_R_remqrdub_-body" aria-labelledby="mantine-_R_remqrdub_-title"><div class="m_a5d60502 mantine-Alert-wrapper"><div class="m_667f2a6a mantine-Alert-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-rocket "><path d="M4 13a8 8 0 0 1 7 7a6 6 0 0 0 3 -5a9 9 0 0 0 6 -8a3 3 0 0 0 -3 -3a9 9 0 0 0 -8 6a6 6 0 0 0 -5 3"></path><path d="M7 14a6 6 0 0 0 -3 6a6 6 0 0 0 6 -3"></path><path d="M14 9a1 1 0 1 0 2 0a1 1 0 1 0 -2 0"></path></svg></div><div class="m_667c2793 mantine-Alert-body"><div class="m_6a03f287 mantine-Alert-title"><span id="mantine-_R_remqrdub_-title" class="m_698f4f23 mantine-Alert-label">Полный доступ к материалам</span></div><div id="mantine-_R_remqrdub_-body" class="m_7fa78076 mantine-Alert-message"><div style="--group-gap:var(--mantine-spacing-md);--group-align:center;--group-justify:space-between;--group-wrap:wrap" class="m_4081bf90 mantine-Group-root"><p class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Зарегистрируйтесь и получите доступ к этому и десяткам других курсов</p><a style="--button-height:var(--button-height-xs);--button-padding-x:var(--button-padding-x-xs);--button-fz:var(--mantine-font-size-xs);--button-bg:linear-gradient(45deg, var(--mantine-color-blue-filled) 0%, var(--mantine-color-cyan-filled) 100%);--button-hover:linear-gradient(45deg, var(--mantine-color-blue-filled) 0%, var(--mantine-color-cyan-filled) 100%);--button-color:var(--mantine-color-white);--button-bd:none" class="mantine-focus-auto mantine-active m_77c9d27d mantine-Button-root m_87cf2631 mantine-UnstyledButton-root" data-variant="gradient" data-size="xs" href="/u/new"><span class="m_80f1301b mantine-Button-inner"><span class="m_811560b9 mantine-Button-label">Зарегистрироваться</span></span></a></div></div></div></div></div><div style="margin-bottom:var(--mantine-spacing-xl)" class=""><div class="ratio ratio-16x9"><iframe width="100%" height="auto" src="//www.youtube.com/embed/rjbt2ga7Ezk" loading="lazy" allowFullScreen="" title="video"></iframe></div></div><div class="paywalled m_d08caa0 mantine-Typography-root"><h2 id="heading-2-1">Транскрипт урока</h2>
<p>Мы уже знакомы со способом называть что-то, используя константы. Например, это константа <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">pi</code> со значением <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">3.14</code>.</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">const pi = 3.14</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>После этой строки, каждый раз, когда мы видим <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">pi</code>, мы знаем, что её значение <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">3.14</code>. Она называется константой, потому что, ээм, она неизменна, постоянна. После этой строки <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">pi</code> всегда будет <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">3.14</code>, это никогда не изменится. Именно поэтому по аналогии с бумагой я использую ручку.</p>
<p>Это может показаться ограничением, но вообще — это довольно хорошее свойство. Изменение того, что мы уже создали — сложная задача. Представьте, что пишете код, используя константу, в значении которой не уверены.</p>
<p>Тем не менее, иногда вам может потребоваться изменить уже существующие данные или, другими словами, их значения. Допустим, вы хотите повторить что-то 5 раз. Один способ — выполнять повторы, отсчитывая до пяти, а затем остановиться. Для этого вам потребуется что-нибудь для хранения счётчика этого меняющегося числа. Константа не будет в таком случае работать — она неизменна, вы не можете изменить её значение после того, как уже создали её.</p>
<p>Поэтому в JavaScript и многих других языках программирования существует идея переменной. Можно представить ее в виде такой же бумажки, на которой имя написано ручкой, но значение — карандашом. В любой момент можно заменить значение на другое.</p>
<p>Можно посчитать факториал с помощью переменной вот так:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">let factorial = 1
factorial = factorial * 2 // 2
factorial = factorial * 3 // 6
factorial = factorial * 4 // 24
factorial = factorial * 5 // 120</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>Создать переменную — просто, она выглядит как константа, только вместо <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">const</code> мы пишем <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">let</code>. Мы позволяем ей быть чем-то и это не навсегда.</p>
<p>Затем мы изменяем значение <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">factorial</code>. Мы бы такого не смогли сделать, если бы <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">factorial</code> был константой. Эта строка означает "изменить значение переменной факториал, на результат умножения факториала на 2". Теперь JavaScript умножает <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">factorial</code> на 2 и хранит этот результат в переменной <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">factorial</code>. Раньше <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">factorial</code> был 1, а теперь это 2.</p>
<p>Мы повторяем это ещё трижды, каждый раз умножая полученное значение на следующее целое число: на 3, на 4 и на 5. Это то, что вы возможно делаете в уме, когда умножаете числа. Вероятно, вы не думали об этом так чётко, но это неплохой способ описания процесса вычисления, если бы вам было нужно объяснить его.</p>
<p>Идея использования счётчика для повторения чего-то множество раз — распространённая в программировании, и большинство языков программирования имеют для этого "циклы". Давайте рассмотрим один тип цикла — "цикл while". Это блок кода, который повторяется, пока удовлетворяется какое-то условие.</p>
<p>Представьте фермера, который работает от рассвета до заката. Другими словами, он работает пока солнце в небе. Вы можете записать:</p>
<code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">while (sun is up) {
work
}</code>
<p>Конечно, это не настоящий JavaScript, это просто чтобы показать идею. Эта строка "work" будет повторяться снова и снова, пока солнце над горизонтом. Это значит после каждого повторения нам нужно проверять, действительно ли солнце в небе, и остановиться если это не так. Другими словами: проверить — исполнить, проверить — исполнить, и так далее.</p>
<p>Вот функция факториала с переменными и циклом вместо рекурсии.</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">const factorial = (n) => {
let counter = 1
let result = 1
while (counter <= n) {
result = result * counter
counter = counter + 1
}
return result
}</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>О-о, что тут происходит? Во-первых, мы создали две переменные: одна для счётчика, чтобы считать от 1 до верхнего предела, а вторая для текущего результата.</p>
<p>Затем начинается главная часть: цикл while, который повторяется, пока счётчик меньше или равен n — числу, переданному в эту функцию. Код, который повторяется, простой: мы меняем значения наших двух переменных. Текущий результат умножается на счётчик, а счётчик увеличивается на 1.</p>
<p>В какой-то момент это условие — "счётчик меньше или равен n" — станет ложным, цикл больше не будет повторяться, а программа перейдёт к следующему этапу — <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">return result</code>. К этому моменту результат станет ответом, потому что за время всех повторов в цикле, результат умножался на 1, затем на 2, 3 и так далее, пока не достиг значения n, каким бы оно ни было.</p>
<p>Давайте посмотрим, что компьютер делает шаг за шагом, когда мы вызываем факториал 3.</p>
<ol>
<li>Взять один аргумент — 3, известный внутри, как <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">n</code></li>
<li>Создать переменную <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">counter</code>, установить значение 1</li>
<li>Создать переменную <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">result</code>, установить значение 1</li>
<li>Проверить: в счётчике — 1, это меньше или равно <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">n</code>, поэтому</li>
<li>Умножить <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">result</code> на <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">counter</code> и положить ответ — 1 — в <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">result</code></li>
<li>Добавить 1 к <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">counter</code> и положить ответ — 2 — в <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">counter</code></li>
<li>Вернуться и проверить: <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">counter</code> — 2, это меньше или равно <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">n</code>, поэтому</li>
<li>Умножить <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">result</code> на <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">counter</code> и положить ответ — 2 — в <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">result</code></li>
<li>Добавить 1 к <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">counter</code> и положить ответ — 3 — в <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">counter</code></li>
<li>Вернуться и проверить: <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">counter</code> — 3, это меньше или равно <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">n</code>, поэтому</li>
<li>Умножить <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">result</code> на <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">counter</code> и положить ответ — 6 — в <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">result</code></li>
<li>Добавить 1 к <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">counter</code> и положить ответ — 4 — в <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">counter</code></li>
<li>Вернуться и проверить: <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">counter</code> — 4, это не меньше и не равно <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">n</code>, поэтому остановить повтор и перейти к следующей строке</li>
<li>Вернуть <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">result</code> — 6</li>
</ol>
<p>Компьютер выполняет такие операции в миллиарды раз быстрее, но по сути это выглядит именно так. Общее название такого вида сформулированных повторений — "итерация". Наша программа использует итерацию, чтобы рассчитать факториал.</p>
<p>В прошлый раз мы рассматривали итеративный процесс с рекурсией, а в этот — итеративный процесс без рекурсии.</p>
<p>Оба используют технику итерации, но с рекурсивными вызовами нам не нужно менять значения, мы просто передаём новые значения в следующий вызов функции. А эта функция факториала не имеет рекурсивных вызовов вообще, поэтому все трансформации должны происходить внутри единственного экземпляра, единственной функциональной коробки. У нас нет выбора, кроме как менять значения содержимого.</p>
<p>Стиль программирования, который вы видели в предыдущих уроках, называется "декларативным". Сегодняшний стиль, с изменением значений, называется "императивным".</p>
<p>Сравните рекурсивный и нерекурсивный факториалы:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">const recursiveFactorial = (n) => {
if (n === 1) {
return 1
}
return n * recursiveFactorial(n - 1)
}
const factorial = (n) => {
let counter = 1
let result = 1
while (counter <= n) {
result = result * counter
counter = counter + 1
}
return result
}</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>Эта рекурсивная функция — декларативная — она как описание факториала. Она объясняет, что такое факториал.</p>
<p>Это нерекурсивная итеративная функция, и она императивная — она описывает, что делать, чтобы найти факториал.</p>
<p>Слово декларативный происходит от латинского "clarare" — <em>разъяснять, заявлять, делать объявление</em>. Вы разъясняете: я хочу, чтобы факториал n был n умножить на факториал n-1.</p>
<p>Слово императивный происходит от латинского "imperare", что значит "<em>командовать</em>". Вы приказываете чётко передвигаться по шагам — умножать это на это, пока идёт отсчёт и запоминать какие-то числа.</p>
<p>Декларативное — это что. Императивное — это как.</p>
<p>Писать декларативный код, в целом, лучший подход. Ваш код будет легче читать, понимать и делать что-то новое опираясь на него. Некоторые языки провоцируют вас использовать тот или иной подход, а некоторые вообще не оставляют выбора.</p>
<p>Но в итоге вам нужно будет научиться оценивать, когда императивный подход принесет больше проблем чем решений.</p>
<p>Следить за изменениями – сложно, и буквально несколько переменных могут сделать систему очень сложной для понимания.</p>
<p>От изменения состояния появляется гора багов, а <strong>оператор присваивания</strong> (<strong>assignment statements</strong>), который создает изменения, часто является причиной всего зла во вселенной.</p>
<h2 id="heading-2-2">Дополнение к уроку</h2>
<h3 id="heading-3-3">var vs let</h3>
<p>Кроме <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">let</code> существует другой способ определения переменных: <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">var a = 5</code>. Этот способ был единственным до появления стандарта ES6, но в современном JavaScript он является устаревшим, и <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">let</code> полностью заменил его.</p>
<p><code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">let</code> и <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">var</code> по-разному влияют на видимость переменной, и использование <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">var</code> сегодня нежелательно. <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">let</code> был создан как более правильная альтернатива старому способу.</p>
<h3 id="heading-3-4">Отладка: Как найти и исправить ошибки</h3>
<p>Наделать ошибок очень легко, когда приходится справляться с переменными, изменять их, отслеживать и всякое такое. Особенно в зацикленном процессе. Прекрасный способ разобраться с тем, что происходит — использовать простейшую технику для отладки — <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">console.log</code>. Вспомните, эта функция выводит в консоль то, что ей передают.</p>
<p>Например, я пытаюсь разобраться, что происходит внутри цикла while:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">while (counter <= n) {
result = result * result
counter = counter + 1
}</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>Добавлю сюда console.log:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">while (counter <= n) {
result = result * result
counter = counter + 1
console.log(result)
}</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>Теперь, каждый раз, когда повторяется этот блок кода, переменная <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">result</code> будет выводиться на экран. Давайте посмотрим:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">1
1
1</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p><em>(Я запускаю функцию с <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">n</code> равным 3)</em></p>
<p>В каждом шаге <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">result</code> — это 1. Не верно — <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">result</code> должен возрастать на каждом шаге… Ок, значит вероятная проблема, в строке, где <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">result</code> меняется. Так и есть! У меня <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">result = result * result</code>, а мне нужно умножить <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">result</code> на <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">counter</code>, а не на <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">result</code>.</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">1
2
6</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>Теперь всё работает! Теперь я вижу шаги и последний шаг выдал верный ответ: 3! это 6. Используйте <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">console.log</code> абсолютно везде. Это ваш лучший друг :-)</p>
<h3 id="heading-3-5">Бесконечные циклы</h3>
<p>Поскольку цикл while только проверяет состояние, мы можем создать бесконечные циклы, если сделаем состояние всегда истинным.</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">while (10 > 5) {
console.log('Ten is still larger than 5')
}</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>Этот код будет выводить на экран "Десять всё ещё больше чем 5" пока не сгорит вселенная или пока вы не закроете программу, ну или пока компьютер не израсходует всю свою память — что бы ни случилось первым. Поскольку состояние <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">10 > 5</code> всегда истинно.</p>
<p>Есть еще более простой способ сделать бесконечный цикл — <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">while (true) { ... }</code>. При этом <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">true</code> всегда истинный.</p>
<p>Иногда ваши циклы будут бесконечными, даже если вы этого не планировали. Это общая проблема, и она указывает только на то, что внутри цикла вы забыли изменить проверяемую деталь. Например, если я удалю строку <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">counter = counter + 1</code> из цикла в сегодняшнем уроке:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">while (counter <= n) {
result = result * result
}</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>… у меня получится бесконечный цикл: counter никогда не меняется, поэтому если <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">counter <= n</code>, условие всегда будет истинно.</p>
<h2 id="heading-2-6">Выводы</h2>
<p><strong>Переменные</strong> подобны константам, но вы можете изменить их значения в любой момент.</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">let age = 21
age = 22 // now age is 22
age = age + 10 // now age is 32</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p><strong>Циклы</strong> — это повторяющиеся блоки кода. <strong>Цикл while</strong> — это блок, повторяющийся пока какое-то <em>состояние</em> истинно.</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">while (condition) {
do_stuff
}</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>Вот факториал функции с циклом while:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">const factorial = (n) => {
let counter = 1
let result = 1
while (counter <= n) {
result = result * counter
counter = counter + 1
}
return result
}</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>Идея: сделать <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">counter</code> = 1, затем умножать <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">result</code> на <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">counter</code> повторно, пока идёт отсчёт до <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">n</code> (число, передаваемое функции). Когда <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">counter</code> станет больше, чем <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">n</code> — остановиться. К тому моменту <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">result</code> будет ответом.</p>
<p>Это <strong>итерация</strong> — сформулированное повторение кода. Разные языки по-разному выполняют итерацию. Цикл while — это один из способов, который предлагает JavaScript.</p>
<h3 id="heading-3-7">Декларативное vs. императивное программирование</h3>
<p>Сравните рекурсивный факториал (из 9 урока) и нерекурсивный факториал (из сегодняшнего):</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">const recursiveFactorial = (n) => {
if (n === 1) {
return 1
}
return n * recursiveFactorial(n - 1)
}
const factorial = (n) => {
let counter = 1
let result = 1
while (counter <= n) {
result = result * counter
counter = counter + 1
}
return result
}</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>Эта рекурсивная функция — <strong>декларативная</strong> — она как бы определение (трактование, характеристика) факториала. Она декларирует, что такое факториал.</p>
<p>Эта нерекурсивная итеративная функция — <strong>императивная</strong> — описание того, что нужно делать, чтобы найти факториал.</p>
<p>Слово декларативный происходит от латинского "clarare" — <em>разъяснять, заявлять, делать объявление</em>. Вы разъясняете: я хочу, чтобы факториал n был n раз факториалом n-1.</p>
<p>Слово императивный происходит от латинского "imperare", что значит "<em>командовать</em>". Вы приказываете чётко передвигаться по шагам — умножать это на это, пока идёт отсчёт и запоминаются какие-то числа.</p>
<blockquote>
<p>Декларативное — это что. Императивное — это как.</p>
</blockquote>
<p>Писать декларативный код, в целом, лучший выбор. Ваш код будет легче читать, понимать и делать что-то новое опираясь на него. Но иногда у вас нет выбора.</p>
<p>От изменения состояния* появляется гора багов, а <strong>инструкции (операторы) присваивания</strong> (<strong>assignment statements</strong>), которые создают изменения, часто являются коренными причинами всего зла во вселенной.</p>
<p>Поэтому, когда дело доходит до инструкций присваивания, <strong>действуйте осторожно</strong>.</p></div></div></div></div><style data-mantine-styles="inline">.__m__-_R_1bdub_{--col-flex-grow:auto;--col-flex-basis:8.333333333333334%;--col-max-width:8.333333333333334%;}@media(min-width: 48em){.__m__-_R_1bdub_{--col-flex-grow:auto;--col-flex-basis:16.666666666666668%;--col-max-width:16.666666666666668%;}}</style><div style="min-width:0rem;height:100%;min-height:0rem" class="m_96bdd299 mantine-Grid-col __m__-_R_1bdub_"><div style="margin-inline:var(--mantine-spacing-xs)" class="mantine-visible-from-sm"><a style="--button-color:var(--mantine-color-white);margin-bottom:var(--mantine-spacing-lg);text-decoration:none" class="mantine-focus-auto m_849cf0da mantine-focus-auto m_77c9d27d mantine-Button-root m_87cf2631 mantine-UnstyledButton-root m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/courses/introduction_to_programming/lessons/while/finish_unit?unit=theory" data-disabled="true" data-block="true" disabled=""><span class="m_80f1301b mantine-Button-inner"><span class="m_811560b9 mantine-Button-label"><span style="margin-inline-end:var(--mantine-spacing-xs)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Дальше</span>→</span></span></a><a style="padding-inline:0rem" class="mantine-focus-auto m_f0824112 mantine-NavLink-root m_87cf2631 mantine-UnstyledButton-root"><span class="m_690090b5 mantine-NavLink-section" data-position="left"><div style="--ti-size:var(--ti-size-sm);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="sm"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-list-numbers "><path d="M11 6h9"></path><path d="M11 12h9"></path><path d="M12 18h8"></path><path d="M4 16a2 2 0 1 1 4 0c0 .591 -.5 1 -1 1.5l-3 2.5h4"></path><path d="M6 10v-6l-2 2"></path></svg></div></span><div class="m_f07af9d2 mantine-NavLink-body"><span class="m_1f6ac4c4 mantine-NavLink-label">Навигация по теме</span><span class="m_57492dcc mantine-NavLink-description">Теория</span></div><span class="m_690090b5 mantine-NavLink-section" data-position="right"></span></a><div style="margin-block:var(--mantine-spacing-lg)" class="m_3eebeb36 mantine-Divider-root" data-orientation="horizontal" role="separator"></div><div style="margin-block:var(--mantine-spacing-lg)" class=""><div style="justify-content:space-between;margin-bottom:calc(0.1875rem * var(--mantine-scale));color:var(--mantine-color-dimmed);font-size:var(--mantine-font-size-xs)" class="m_8bffd616 mantine-Flex-root __m__-_R_qimrbdub_"><p style="font-size:var(--mantine-font-size-xs)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Завершено</p><p style="font-size:var(--mantine-font-size-xs)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">0 / 20</p></div><div style="--progress-size:var(--progress-size-sm)" class="m_db6d6462 mantine-Progress-root" data-size="sm"><div style="--progress-section-size:0%;--progress-section-color:var(--mantine-color-gray-filled)" class="m_2242eb65 mantine-Progress-section" role="progressbar" aria-valuemax="100" aria-valuemin="0" aria-valuenow="0" aria-valuetext="0%"></div></div></div><button style="padding-inline:0rem" class="mantine-focus-auto m_f0824112 mantine-NavLink-root m_87cf2631 mantine-UnstyledButton-root" type="button"><span class="m_690090b5 mantine-NavLink-section" data-position="left"><div style="--ti-size:var(--ti-size-sm);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="sm"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-message "><path d="M8 9h8"></path><path d="M8 13h6"></path><path d="M18 4a3 3 0 0 1 3 3v8a3 3 0 0 1 -3 3h-5l-5 3v-3h-2a3 3 0 0 1 -3 -3v-8a3 3 0 0 1 3 -3h12"></path></svg></div></span><div class="m_f07af9d2 mantine-NavLink-body"><span class="m_1f6ac4c4 mantine-NavLink-label">Обсуждения (архив)</span><span class="m_57492dcc mantine-NavLink-description"></span></div></button><div style="--toc-bg:var(--mantine-color-blue-light);--toc-color:var(--mantine-color-blue-light-color);--toc-size:var(--mantine-font-size-sm);--toc-radius:var(--mantine-radius-sm);margin-top:var(--mantine-spacing-xl)" class="m_bcaa9990 mantine-TableOfContents-root" data-variant="light" data-size="sm"></div></div><div class="mantine-hidden-from-sm"><div style="--stack-gap:0rem;--stack-align:stretch;--stack-justify:flex-start" class="m_6d731127 mantine-Stack-root"><a style="--button-color:var(--mantine-color-white);margin-bottom:var(--mantine-spacing-xs);padding:0rem;text-decoration:none" class="mantine-focus-auto m_849cf0da mantine-focus-auto m_77c9d27d mantine-Button-root m_87cf2631 mantine-UnstyledButton-root m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/courses/introduction_to_programming/lessons/while/finish_unit?unit=theory" data-disabled="true" data-block="true" disabled=""><span class="m_80f1301b mantine-Button-inner"><span class="m_811560b9 mantine-Button-label">→</span></span></a><button style="--ai-size:var(--ai-size-sm);--ai-bg:transparent;--ai-hover:var(--mantine-color-indigo-light-hover);--ai-color:var(--mantine-color-indigo-light-color);--ai-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;padding-block:var(--mantine-spacing-lg);color:inherit;width:100%" class="mantine-focus-auto m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="subtle" data-size="sm" data-disabled="true" type="button" disabled=""><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-list-numbers "><path d="M11 6h9"></path><path d="M11 12h9"></path><path d="M12 18h8"></path><path d="M4 16a2 2 0 1 1 4 0c0 .591 -.5 1 -1 1.5l-3 2.5h4"></path><path d="M6 10v-6l-2 2"></path></svg></span></button><button style="--ai-size:var(--ai-size-sm);--ai-bg:transparent;--ai-hover:var(--mantine-color-indigo-light-hover);--ai-color:var(--mantine-color-indigo-light-color);--ai-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;padding-block:var(--mantine-spacing-lg);color:inherit;width:100%" class="mantine-focus-auto mantine-active m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="subtle" data-size="sm" type="button"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-message "><path d="M8 9h8"></path><path d="M8 13h6"></path><path d="M18 4a3 3 0 0 1 3 3v8a3 3 0 0 1 -3 3h-5l-5 3v-3h-2a3 3 0 0 1 -3 -3v-8a3 3 0 0 1 3 -3h12"></path></svg></span></button></div></div></div></div></div></div></div>
</main>
<footer class="bg-dark fw-light text-light px-3 py-5">
<div class="row small">
<div class="col-12 col-sm-6 col-md-3">
<div class="h5 mb-3">Хекслет</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/about">О нас</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/testimonials">Отзывы</a>
</li>
<li>
<span class="nav-link link-light py-1 ps-0 external-link" data-href="https://b2b.hexlet.io" role="button">Корпоративное обучение</span>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/blog">Блог</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/qna">Вопросы и ответы</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/glossary">Глоссарий</a>
</li>
<li>
<span class="nav-link link-light py-1 ps-0 external-link" data-href="https://help.hexlet.io" data-target="_blank" role="button">Справка</span>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" target="_blank" rel="noopener noreferrer" href="/map">Карта сайта</a>
</li>
</ul>
</div>
<div class="col-12 col-sm-6 col-md-3">
<div class="h5 fw-normal mb-3">Направления</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_devops">DevOps
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_data_analytics">Аналитика
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_backend_development">Бэкенд
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_programming">Программирование
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_testing">Тестирование
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_front_end_dev">Фронтенд
</a></li>
</ul>
</div>
<div class="col-12 col-sm-6 col-md-3">
<div class="h5">Профессии</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/devops-engineer-from-scratch">DevOps-инженер с нуля</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/go">Go-разработчик</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/java">Java-разработчик</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/python">Python-разработчик </a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/data-analytics">Аналитик данных</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/qa-engineer">Инженер по ручному тестированию</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/php">РНР-разработчик</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/frontend">Фронтенд-разработчик</a>
</li>
</ul>
</div>
<div class="col-12 col-sm-6 col-md-3">
<div class="h5">Навыки</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/python-django-developer">Django</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/docker">Docker</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/php-laravel-developer">Laravel</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/postman">Postman</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/js-react-developer">React</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/js-rest-api">REST API в Node.js</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/spring-boot">Spring Boot</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/typescript">Typescript</a>
</li>
</ul>
</div>
</div>
<hr>
<div class="row">
<div class="col-12 col-sm-4 col-md-2">
<div class="fs-4">
<ul class="list-unstyled d-flex">
<li class="me-3">
<a aria-label="Telegram" target="_blank" class="link-light" rel="noopener noreferrer nofollow" href="https://t.me/hexlet_ru"><span class="bi bi-telegram"></span>
</a></li>
<li>
<a aria-label="Youtube" target="_blank" class="link-light" rel="noopener noreferrer nofollow" href="https://www.youtube.com/user/HexletUniversity"><span class="bi bi-youtube"></span>
</a></li>
</ul>
</div>
<div class="mb-2 d-flex flex-column">
<a class="link-light text-decoration-none" rel="nofollow" href="mailto:support@hexlet.io">support@hexlet.io</a>
<a class="link-light text-decoration-none py-2" target="_blank" href="https://t.me/hexlet_help_bot">t.me/hexlet_help_bot</a>
</div>
<ul class="list-unstyled d-flex">
<li class="me-3">
<span class="link-light text-decoration-none opacity-50 x-font-size-18 external-link" rel="nofollow" data-href="https://hexlet.io/locale/switch?new_locale=en" data-target="_self" role="button"><span class="my-auto">EN</span>
</span></li>
<li class="me-3">
<span class="link-light text-decoration-none opacity-50 x-font-size-18 opacity-100 external-link" rel="nofollow" data-href="https://ru.hexlet.io/locale/switch?new_locale=ru" data-target="_self" role="button"><span class="my-auto">RU</span>
</span></li>
<li class="me-3">
<span class="link-light text-decoration-none opacity-50 x-font-size-18 external-link" rel="nofollow" data-href="https://kz.hexlet.io/locale/switch?new_locale=kz" data-target="_self" role="button"><span class="my-auto">KZ</span>
</span></li>
</ul>
</div>
<div class="col-12 col-sm-4 col-md-3">
<ul class="list-unstyled fs-4">
<li class="mb-3">
<a class="link-light text-decoration-none" href="tel:8%20800%20100%2022%2047">8 800 100 22 47</a>
<span class="d-block opacity-50 small">бесплатно по РФ</span>
</li>
<li>
<a class="link-light text-decoration-none" href="tel:%2B7%20495%20085%2021%2062">+7 495 085 21 62</a>
<span class="d-block opacity-50 small">бесплатно по Москве</span>
</li>
</ul>
</div>
<div class="col-12 col-sm-4 col-md-3">
<div class="small mb-3">Образовательные услуги оказываются на основании Л035-01298-77/01989008 от 14.03.2025</div>
<ul class="list-unstyled small">
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/legal">Правовая информация</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/offer">Оферта</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/license">Лицензия</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/contacts">Контакты</a>
</li>
</ul>
</div>
<div class="col-12 col-sm-12 col-md-4 small">
<div class="mb-2">
<div>ООО «<a href="/" class="text-decoration-none link-light">Хекслет Рус</a>»</div>
<div>108813 г. Москва, вн.тер.г. поселение Московский,</div>
<div>г. Московский, ул. Солнечная, д. 3А, стр. 1, помещ. 20Б/3</div>
<div>ОГРН 1217300010476</div>
<div>ИНН 7325174845</div>
</div>
<hr>
<div>АНО ДПО «<a href="/" class="text-decoration-none link-light">Учебный центр «Хекслет</a>»</div>
<div>119331 г. Москва, вн. тер. г. муниципальный округ</div>
<div>Ломоносовский, пр-кт Вернадского, д. 29</div>
<div>ОГРН 1247700712390</div>
<div>ИНН 7736364948</div>
</div>
</div>
</footer>
<div id="root-assistant-offcanvas"></div>
<script src="/vite/assets/assistant-CdBlNCiQ.js" crossorigin="anonymous" type="module"></script><link rel="modulepreload" href="/vite/assets/chunk-DsPFFUou.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/init-nkZBEvfU.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/ErrorFallbackBlock-naDSYSy9.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/MarkdownBlock-DbyKWoR_.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/gon-D3e4yh1x.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/mantine-CGMYrt2Y.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/shiki-V011pkdv.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/utils-DRqSHbQE.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/routes-CCH8ilKF.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/lib-XR8Qr8kR.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/dist-GCHh59xr.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Box-B5-OOzBf.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/notifications.store-C-3AFSMn.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/useIsomorphicEffect-HJ6VK0D3.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/lib-KSp6QbZ0.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/axios-BEvgo0ym.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/classnames-l6ipYlLR.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/dayjs.min-BkKovM-s.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/debounce-jMQ_Cf4f.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/i18next-BlSq9s7B.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/client-U9M77rxp.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-dom-DaLxUz_h.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/useTranslation-Bx1Cdrkz.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/compiler-runtime-6XxiPFnt.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/jsx-runtime-CwjcCKJi.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-CkL4ZRHB.js" as="script" crossorigin="anonymous">
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v67327c56f0bb4ef8b305cae61679db8f1769101564043" integrity="sha512-rdcWY47ByXd76cbCFzznIcEaCN71jqkWBBqlwhF1SY7KubdLKZiEGeP7AyieKZlGP9hbY/MhGrwXzJC/HulNyg==" data-cf-beacon='{"version":"2024.11.0","token":"d11015b65d11429ea6b4a2ef37dd7e0b","server_timing":{"name":{"cfCacheStatus":true,"cfEdge":true,"cfExtPri":true,"cfL4":true,"cfOrigin":true,"cfSpeedBrain":true},"location_startswith":null}}' crossorigin="anonymous"></script>
</body>
</html>