<!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 22:26:52 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="t8Df0NkkJFp703A-AUhGw5c9a6dscM6c_sxBCmdg6IFYERTnK1qJOs2QVKYNR7a0VzRGDWRHMD5DLNteNWcP7w";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>Guard Expression | JS: Функциональное программирование</title>
<meta name="description" content="Guard Expression / JS: Функциональное программирование: Учимся уменьшать сложность функций">
<link rel="canonical" href="https://ru.hexlet.io/courses/js-functions-hard-way/lessons/guard-expression/theory_unit">
<meta name="robots" content="noarchive">
<meta property="og:title" content="Guard Expression">
<meta property="og:title" content="JS: Функциональное программирование">
<meta property="og:description" content="Guard Expression / JS: Функциональное программирование: Учимся уменьшать сложность функций">
<meta property="og:url" content="https://ru.hexlet.io/courses/js-functions-hard-way/lessons/guard-expression/theory_unit">
<meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="jd7hrn33v_pkyZXnONG2o6YfAhgOmfVcckhW3AxxT9hiDyqZj4kSmtKKsX803kbUZhYvsgauC_7PqMyIXnaotg" />
<script src="/vite/assets/inertia-DfXos102.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-BrRXra1y.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-cb8xch9l.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">
<link rel="preload" as="image" href="https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6Mzc2MCwicHVyIjoiYmxvYl9pZCJ9fQ==--9348098e4053d798b6f34bee4ef66947540261e4/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Low%20code%20development-rafiki.png"/><link rel="preload" as="image" href="/vite/assets/development-BVihs_d5.png"/><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-26T22:26:52.064Z","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":"xD5n9jQoy6iBtycP1EtHVyh4j_qvWnzEkRABWGefLMcr76zBxlZmyDf0A5fYRLcg6HGiUKdtgmYs8JsMNZjLqQ","topics":[{"id":31925,"title":"В чем ошибка у меня не пойму, проверял в хроме все работает...\n\n`// removed`","plain_title":"В чем ошибка у меня не пойму, проверял в хроме все работает... const isPalindrome = (s) => { const length = s.length; if (length === 1) { return true; } else { return (s.substr(0, 1) === s.substr(-1)) ? isPalindrome(s.substr(1,length - 2)) : false; } }; ","creator":{"public_name":"Ilja Aktsurin","id":66836,"is_tutor":false},"comments":[{"creator":{"public_name":"Ilja Aktsurin","id":66836,"is_tutor":false},"id":69342,"body":"спасибо, да точно не проверил условие на 0, вывод ошибки меня просто смутил и в другую сторону копал...","topic_id":31925},{"creator":{"public_name":"Макс Лантинов","id":227791,"is_tutor":false},"id":69331,"body":"Привет. у тебя на второй итерации строка становится = '', т.е. её length = 0. Разберись, что будет происходить если вызвать isPalindrome('');","topic_id":31925}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Guard Expression","entity_url":null,"active":true}},{"id":28430,"title":"Привет! Подскажите пожалуйста по коду ниже, не могу понять в чём загвоздка. В ошибках - превышен максимальный стек вызова. На pythontutor`е проследил, за вычислениями, вроде как должно всё работать должно.\n```const isPalindrome = (str) => {\n if (str.length === 1) {\n return true;\n }\n return (str[0] === str[str.length - 1]) ? isPalindrome(str.slice(1, str.length - 1)) : false\n};\n```","plain_title":"Привет! Подскажите пожалуйста по коду ниже, не могу понять в чём загвоздка. В ошибках - превышен максимальный стек вызова. На pythontutorе проследил, за вычислениями, вроде как должно всё работать должно. const isPalindrome = (str) => { if (str.length === 1) { return true; } return (str[0] === str[str.length - 1]) ? isPalindrome(str.slice(1, str.length - 1)) : false }; ` ","creator":{"public_name":"Eugene Koretsky","id":211271,"is_tutor":false},"comments":[{"creator":{"public_name":"Eugene Koretsky","id":211271,"is_tutor":false},"id":61261,"body":"Ааа, проанализировав какие аргументы поступают в функцию, понял что спотыкается она только на строке из двух символов. Осталось решить)","topic_id":28430}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Guard Expression","entity_url":null,"active":true}},{"id":27686,"title":"```\n // BEGIN (write your solution here)\n const isPalindrome = (str) => {\n let i = 0;\n if (str.length <= 2) {\n return true;\n } if (str[i] === str[str.length - 1 - i]) {\n return true;\n i = i + 1;\n } if (str[i] !== str[str.length - 1 - i]) {\n return false;\n }\n};\n\nexport default isPalindrome;\n// END\n```\nВсё. встала и не знаю, что делать???","plain_title":" // BEGIN (write your solution here) const isPalindrome = (str) => { let i = 0; if (str.length <= 2) { return true; } if (str[i] === str[str.length - 1 - i]) { return true; i = i + 1; } if (str[i] !== str[str.length - 1 - i]) { return false; } }; export default isPalindrome; // END Всё. встала и не знаю, что делать??? ","creator":{"public_name":"Вера Ковалева","id":211806,"is_tutor":false},"comments":[{"creator":{"public_name":"Сергей К.","id":5174,"is_tutor":false},"id":59530,"body":"Вера, добрый день! Расскажите, как успехи? Удалось решить задачу?","topic_id":27686},{"creator":{"public_name":"Ruslan Hamidullin","id":121967,"is_tutor":false},"id":59478,"body":"Вы совсем забыли о рекурсии","topic_id":27686},{"creator":{"public_name":"Dmitriy Bataev","id":106130,"is_tutor":false},"id":59398,"body":"```\nif (str[i] === str[str.length - 1 - i]) {\n return true;\n i = i + 1;\n}\n```\nДело в том, чтобы проверить строку на полиндром недостаточно просто проверить первый и последний элемент строки (Кстати индекс у последнего `str.length - 1`), нужно проверку продолжить и для внутренней строки (строка `return true` не оставляет возможности продолжить проверку).\n\nP.s. Строят цепочку условий иначе:\n```\nif (condition1) {\n ...\n} else if (condition2) {\n ...\n} else {\n ...\n}\n```","topic_id":27686}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Guard Expression","entity_url":null,"active":true}},{"id":32033,"title":"Коллеги, подскажите: когда linter ругается, после перечня ошибок пишется подобное:\n\n`3 errors and 0 warnings potentially fixable with the `--fix` option.`.\n\n`--fix` можно использовать в терминале учебном?\n\nПосмотрел [--fix ESLint](https://eslint.org/docs/user-guide/migrating-from-jscs#--fix) - не работают команды в терминале.\nВ [ESLint](https://eslint.org/docs/rules/) заглядываю часто, но иногда встречаю крайне неочевидные примеры оформления кода(\n\n[Ревью](https://ru.hexlet.io/code_reviews/149377) | `error Unnecessary 'else' after 'return' no-else-return` | [ESLint no-else-return](https://eslint.org/docs/rules/no-else-return)","plain_title":"Коллеги, подскажите: когда linter ругается, после перечня ошибок пишется подобное: 3 errors and 0 warnings potentially fixable with the--fixoption.. --fix можно использовать в терминале учебном? Посмотрел --fix ESLint (https://eslint.org/docs/user-guide/migrating-from-jscs#--fix) - не работают команды в терминале. В ESLint (https://eslint.org/docs/rules/) заглядываю часто, но иногда встречаю крайне неочевидные примеры оформления кода( ","creator":{"public_name":"Сергей Чепухин","id":177876,"is_tutor":false},"comments":[{"creator":{"public_name":"Nikita Mikhaylov","id":186965,"is_tutor":true},"id":69593,"body":"Здравствуйте\n\nВ учебном фикс не поможет :) В данном случае обратите внимание на документацию, которую вы приложили. \n\nПравило `no-else-return` просит не писать `return` внутри `else`. На самом деле причина такого требования проста — это лишний код. Если внутри `else` вам необходим `return` (при условии, что в других ветвях тоже есть `return`), то его можно спокойно вынести и не писать `else`. Логика кода не нарушится, а читать код станет приятнее.\n\nВместо\n\n if (...) {\n return ...\n } else {\n return ...\n }\n\nКороче и понятнее будет написать\n\n if (...) {\n return ...\n }\n\n return ...","topic_id":32033}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Guard Expression","entity_url":null,"active":true}},{"id":30026,"title":"Первое что пришло в голову подключить функцию reverseString из предыдущих заданий и в функции isPalindrome уже сравнивать строки. Если равны то true. Потом перечитал задание где описан четкий алгоритм действий. Правильно готовят, что в правильно поставленном вопросе содержится половина ответа.","plain_title":"Первое что пришло в голову подключить функцию reverseString из предыдущих заданий и в функции isPalindrome уже сравнивать строки. Если равны то true. Потом перечитал задание где описан четкий алгоритм действий. Правильно готовят, что в правильно поставленном вопросе содержится половина ответа. ","creator":{"public_name":"","id":4763,"is_tutor":false},"comments":[{"creator":{"public_name":"Александр О.","id":61806,"is_tutor":false},"id":65043,"body":"> Потом перечитал задание где описан четкий алгоритм действий. Правильно готовят, что в правильно поставленном вопросе содержится половина ответа.\n\nУгу ;)","topic_id":30026}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Guard Expression","entity_url":null,"active":true}},{"id":19162,"title":"`// removed`\n\nВыдает ошибку:\n\n`RangeError: Maximum call stack size exceeded`\n\nХотя на pythontutor.com работает без ошибок. Несколько часов сижу и не понимаю в чем может быть проблема.","plain_title":"// removed Выдает ошибку: RangeError: Maximum call stack size exceeded Хотя на pythontutor.com работает без ошибок. Несколько часов сижу и не понимаю в чем может быть проблема. ","creator":{"public_name":"Mikhail Chubakov","id":188452,"is_tutor":false},"comments":[{"creator":{"public_name":"Mikhail Chubakov","id":188452,"is_tutor":false},"id":40547,"body":"Спасибо. Не учел строки с четным количеством символов. Теперь все работает!","topic_id":19162},{"creator":{"public_name":"Александр О.","id":61806,"is_tutor":false},"id":40508,"body":"Добрый день!\n\n> Выдает ошибку:\n\n`Maximum call stack size exceeded` - похоже, что при определённых вызовах ваша функция уходит в \"бесконечную рекурсию\". То есть никогда не достигается терминальное условие.\n\n> Хотя на pythontutor.com работает без ошибок. Несколько часов сижу и не понимаю в чем может быть проблема.\n\nПроанализируйте модуль с тестами (`__tests__/isPalindrome.test.js`), посмотрите с какими аргументами там вызывается ваша функция. Чтобы удостовериться, что действительно работает без ошибок, вы должны проверить свою функцию со всеми этими аргументами. Судя по тестами, на каком-то из них возникает бесконечная рекурсия.","topic_id":19162}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Guard Expression","entity_url":null,"active":true}},{"id":10764,"title":"Здравствуйте.\nВ задании, как мне кажется, ошибка.\nВ функции `substr('hello', 0, 4); // => \"hell\"` задания 2-й аргумент -\n позиция знака в строке, 3-й - количество знаков.\nОднако проверку проходит только если наоборот: 2-й аргумент - количество знаков, 3-й позиция в строке((( ","plain_title":"Здравствуйте. В задании, как мне кажется, ошибка. В функции substr('hello', 0, 4); // => \"hell\" задания 2-й аргумент - позиция знака в строке, 3-й - количество знаков. Однако проверку проходит только если наоборот: 2-й аргумент - количество знаков, 3-й позиция в строке((( ","creator":{"public_name":"Liubov Kudrina","id":139762,"is_tutor":false},"comments":[{"creator":{"public_name":"Liubov Kudrina","id":139762,"is_tutor":false},"id":22427,"body":"Доброй ночи.\nЯ не смогла пройти это задание, поэтому решение скорее Ваше, чем мое. Уже перешла к следующему уроку, поэтому отправить код на ревью не смогу(( Или есть возможность вернуться к заданию?\nЕсли кратко: пыталась решить с кодом `// removed`, в OUTPUT выводилось _Undefined_, когда посмотрела _Решение учителя_, изменила на `// removed`, проверку прошла.","topic_id":10764},{"creator":{"public_name":"Kirill Mokevnin","id":1,"is_tutor":false},"id":22442,"body":"Вы всегда можете тыкнуть кнопку \"практика\" на странице курсов к соответствующему уроку. А там снова послать код на проверку и ревью.","topic_id":10764},{"creator":{"public_name":"Kirill Mokevnin","id":1,"is_tutor":false},"id":22405,"body":"Вероятно ошибка где-то в другом месте. Отправьте ваше решение на код ревью и приложите сюда ссылку, я посмотрю.","topic_id":10764}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Guard Expression","entity_url":null,"active":true}},{"id":27240,"title":"На тестах выдает undefined. Подскажите, пожалуйста, в чем ошибка?\n\n`// removed`","plain_title":"На тестах выдает undefined. Подскажите, пожалуйста, в чем ошибка? // removed ","creator":{"public_name":"Alena Zueva","id":211895,"is_tutor":false},"comments":[{"creator":{"public_name":"Alena Zueva","id":211895,"is_tutor":false},"id":58398,"body":"**Георгий Ратиани**, спасибо!","topic_id":27240},{"creator":{"public_name":"","id":215628,"is_tutor":false},"id":58395,"body":"В блоке `if` данной программы отсутствует возвращаемое значение, поэтому на выходе мы получаем `undefined`.","topic_id":27240}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Guard Expression","entity_url":null,"active":true}},{"id":10635,"title":"как сделать что то похожее на консоль лог ? Хочется посмотреть что у меня в определенном моменте в программе и что у меня в конкретной переменной хранится и т д","plain_title":"как сделать что то похожее на консоль лог ? Хочется посмотреть что у меня в определенном моменте в программе и что у меня в конкретной переменной хранится и т д ","creator":{"public_name":"Александр Немиров","id":139429,"is_tutor":false},"comments":[{"creator":{"public_name":"Александр О.","id":61806,"is_tutor":false},"id":22067,"body":"Дык, а ошибка то какая? Может быть просто до console.log в функции управление не дошло, т.к. ошибка произошла раньше?","topic_id":10635},{"creator":{"public_name":"Александр О.","id":61806,"is_tutor":false},"id":22109,"body":"> Почему в примерах функции из импорта используются так strings.substr\n\nименно потому, что это является примером использования функции, импортированной из модуля. Хотя данный пример скорее неудачный - дело в том, что синтаксис обращения к функции зависит от [способа её импорта](https://ru.hexlet.io/courses/programming-basics/lessons/modules/theory_unit), а этих способов может быть несколько. Я сейчас подкорректировал readme практики, спасибо за замечание.\n\n> а на деле просто substr\n\nа на деле, при работе с модулем, вы сразу же должны проанлизировать расположенные в нем инструкции импорта, например `import { length, substr } from './strings';`, чтобы понять, какие функции из других модулей доступны для вас в текущем модуле и как к этим функциям можно обращаться. Приведённый выше пример импорта предполагает вполне однозначный способ обращения. Возможно, вас стоит повторить урок про модули.","topic_id":10635},{"creator":{"public_name":"Александр Немиров","id":139429,"is_tutor":false},"id":22066,"body":"// removed","topic_id":10635},{"creator":{"public_name":"Александр О.","id":61806,"is_tutor":false},"id":22075,"body":"> Но сейчас мне пишут тесты, что функции strings не существует\n\nПравильно пишут. Что такое `strings` в вашем коде? Откуда вы её (сущность с таким идентификатором) взяли, где она была определена?","topic_id":10635},{"creator":{"public_name":"Александр О.","id":61806,"is_tutor":false},"id":22064,"body":"скиньте скриншот, где виден вывод терминала и ваш код","topic_id":10635},{"creator":{"public_name":"Александр Немиров","id":139429,"is_tutor":false},"id":22074,"body":"Одну ошибку понял, не внимательно прочитал задание, сделал просто экспорт.\n\nНо сейчас мне пишут тесты, что функции strings не существует, может я снова что то не так написал? \n\n// removed","topic_id":10635},{"creator":{"public_name":"Александр Немиров","id":139429,"is_tutor":false},"id":22118,"body":"Спасибо большое! Урок про модули и в правду нужно повторить, задание решено!","topic_id":10635},{"creator":{"public_name":"Александр О.","id":61806,"is_tutor":false},"id":22046,"body":"Добрый день!\n\nВы можете спокойно [отлаживать, используя `console.log`](https://ru.hexlet.io/courses/programming-basics/lessons/debug/theory_unit). Запуск проверки вашего кода осуществляется по нажатию кнопки \"Проверить\" либо запуска команды `make test` в терминале. Результаты (в т.ч. вывод с пощью `console.log` будут видны на вкладке `OUTPUT` или в терминале соответственно.","topic_id":10635},{"creator":{"public_name":"Александр Немиров","id":139429,"is_tutor":false},"id":22068,"body":"// removed","topic_id":10635},{"creator":{"public_name":"Александр Немиров","id":139429,"is_tutor":false},"id":22065,"body":"","topic_id":10635},{"creator":{"public_name":"Александр Немиров","id":139429,"is_tutor":false},"id":22063,"body":"Вот это выводится в терминале через make test\n`const string = 'a123';\n console.log(string);\n \n export const isPalindrome = (string) => {\n return console.log(string);\n}`\n\nА вот консоль лог в функции уже не показывается.","topic_id":10635},{"creator":{"public_name":"Александр Немиров","id":139429,"is_tutor":false},"id":22097,"body":"Она же была импортирована, а в примерах показано как пользоваться, я так и сделал ","topic_id":10635},{"creator":{"public_name":"Александр О.","id":61806,"is_tutor":false},"id":22069,"body":"Вы сейчас даёте скрины двух разных выводов тестов, где проверялись разные версии вашего кода. Что вы хотите на это услашыть? На втором скрине видна ошибка экспорта: тестовый модуль ожидает от вас функцию, экспортированную по умолчанию, но не получает её. Вы сделали экспорт по умолчанию функции, как того требует задание?","topic_id":10635},{"creator":{"public_name":"Александр Немиров","id":139429,"is_tutor":false},"id":22101,"body":"Почему в примерах функции из импорта используются так `strings.substr`, а на деле просто `substr`","topic_id":10635},{"creator":{"public_name":"Александр Немиров","id":139429,"is_tutor":false},"id":22044,"body":"Может это как то можно через терменал делать ? вызов через node имяфайла.js не работает так как импорты в ноде пишутся по другому ","topic_id":10635}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Guard Expression","entity_url":null,"active":true}},{"id":24220,"title":"`// removed`\n","plain_title":"// removed ","creator":{"public_name":"Michael Potapenko","id":205104,"is_tutor":false},"comments":[{"creator":{"public_name":"Сергей К.","id":5174,"is_tutor":false},"id":51654,"body":"Михаил, нет необходимости разносить вопрос по разным топикам. Пишите в одном. Также постарайтесь оформлять сообщения с помощью языка разметки Markdown - https://guides.hexlet.io/markdown/","topic_id":24220}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Guard Expression","entity_url":null,"active":true}}],"lesson":{"exercise":{"id":644,"slug":"js_functions_hard_way_guard_expression_exercise","name":null,"state":"active","kind":"exercise","language":"javascript","locale":"ru","has_web_view":false,"has_test_view":false,"reviewable":true,"readme":"_(Убедитесь в том, что вы решили хотя бы несколько дополнительных практик после курса \"Введение в программирование\")_\n\nПалиндром — число, слово или текст, одинаково читающееся в обоих направлениях. Например: радар, топот.\n\n## isPalindrome.js\n\nРеализуйте и экспортируйте по умолчанию функцию с использованием рекурсии.\n\n### Примеры\n\n```javascript\nimport isPalindrome from './isPalindrome';\n\nisPalindrome('radar'); // true\nisPalindrome('a'); // true\nisPalindrome('abs'); // false\n```\n\nОдин из способов реализовать эту функцию — попарно сравнить буквы, стоящие зеркально относительно центра. Если они совпадают, то перед нами палиндром.\n\n### Алгоритм\n\n1. Если строка короче двух символов, то считается, что это палиндром\n2. Проверяем, совпадают ли первый и последний символы. Если нет, то это не палиндром. Если совпадают, то вызываем функцию рекурсивно, передавая внутрь строку минус первый и последний символ\n\nРазбор на примере: `radar` (палиндром)\n\n1. Первый и последний символ `r`. Так как символы совпали, вызываем `isPalindrome` рекурсивно. Дальше передаем `ada`\n1. Первый и последний символ `a`. Так как символы совпали, вызываем `isPalindrome` рекурсивно. Дальше передаем `d`\n1. Так как длина строки `d` меньше двух символов, возвращаем `true`\n\nРазбор на примере: `rador` (не палиндром)\n\n1. Первый и последний символ `r`. Так как символы совпали, вызываем `isPalindrome` рекурсивно. Дальше передаем `ado`\n1. Первый символ `a` и последний символ `o`. Так как символы не совпали, возвращаем `false`\n\n### Подсказки\n\n* Чтобы узнать длину строки, используйте свойство `length`:\n\n ```javascript\n 'hello'.length; // 5\n ```\n\n* Чтобы получить подстроку из строки, используйте метод `substring`:\n\n ```javascript\n 'hello'.substring(0, 4); // \"hell\"\n 'hello'.substring(1, 3); // \"el\"\n ```\n","prepared_readme":"_(Убедитесь в том, что вы решили хотя бы несколько дополнительных практик после курса \"Введение в программирование\")_\n\nПалиндром — число, слово или текст, одинаково читающееся в обоих направлениях. Например: радар, топот.\n\n## isPalindrome.js\n\nРеализуйте и экспортируйте по умолчанию функцию с использованием рекурсии.\n\n### Примеры\n\n```javascript\nimport isPalindrome from './isPalindrome';\n\nisPalindrome('radar'); // true\nisPalindrome('a'); // true\nisPalindrome('abs'); // false\n```\n\nОдин из способов реализовать эту функцию — попарно сравнить буквы, стоящие зеркально относительно центра. Если они совпадают, то перед нами палиндром.\n\n### Алгоритм\n\n1. Если строка короче двух символов, то считается, что это палиндром\n2. Проверяем, совпадают ли первый и последний символы. Если нет, то это не палиндром. Если совпадают, то вызываем функцию рекурсивно, передавая внутрь строку минус первый и последний символ\n\nРазбор на примере: `radar` (палиндром)\n\n1. Первый и последний символ `r`. Так как символы совпали, вызываем `isPalindrome` рекурсивно. Дальше передаем `ada`\n1. Первый и последний символ `a`. Так как символы совпали, вызываем `isPalindrome` рекурсивно. Дальше передаем `d`\n1. Так как длина строки `d` меньше двух символов, возвращаем `true`\n\nРазбор на примере: `rador` (не палиндром)\n\n1. Первый и последний символ `r`. Так как символы совпали, вызываем `isPalindrome` рекурсивно. Дальше передаем `ado`\n1. Первый символ `a` и последний символ `o`. Так как символы не совпали, возвращаем `false`\n\n### Подсказки\n\n* Чтобы узнать длину строки, используйте свойство `length`:\n\n ```javascript\n 'hello'.length; // 5\n ```\n\n* Чтобы получить подстроку из строки, используйте метод `substring`:\n\n ```javascript\n 'hello'.substring(0, 4); // \"hell\"\n 'hello'.substring(1, 3); // \"el\"\n ```\n","has_solution":true,"entity_name":"Guard Expression"},"units":[{"id":2028,"name":"theory","url":"/courses/js-functions-hard-way/lessons/guard-expression/theory_unit"},{"id":2039,"name":"quiz","url":"/courses/js-functions-hard-way/lessons/guard-expression/quiz_unit"},{"id":2035,"name":"exercise","url":"/courses/js-functions-hard-way/lessons/guard-expression/exercise_unit"}],"links":[],"ordered_units":[{"id":2028,"name":"theory","url":"/courses/js-functions-hard-way/lessons/guard-expression/theory_unit"},{"id":2039,"name":"quiz","url":"/courses/js-functions-hard-way/lessons/guard-expression/quiz_unit"},{"id":2035,"name":"exercise","url":"/courses/js-functions-hard-way/lessons/guard-expression/exercise_unit"}],"id":978,"slug":"guard-expression","state":"approved","name":"Guard Expression","course_order":150,"goal":"Учимся уменьшать сложность функций","self_study":null,"theory_video_provider":null,"theory_video_uid":null,"theory":"Одни функции устроены сложнее других. Иногда так происходит в силу объективных причин (необходимая сложность). Иногда — в силу особенностей писавшего ее программиста (случайная сложность). И хотя нельзя однозначно описать эту сложность, существуют способы, позволяющие хотя бы частично ее оценить.\n\n## Цикломатическая сложность\n\nЦикломатическая сложность — это структурная или топологическая мера сложности компьютерной программы, разработанная Томасом Дж. Маккейбом в 1976 году.\n\nЦикломатическая сложность части программного кода — количество линейно независимых маршрутов через программный код. Если исходный код не содержит никаких точек ветвления или циклов, то сложность равна единице, поскольку есть только один маршрут через код.\n\nЕсли код имеет единственный оператор `if`, содержащий простое условие, то существует два пути через код: один, если условие оператора `if` имеет значение `true`, и один — если `false`.\n\n\n\nТакую оценку можно применять как в целом к программе, так и к отдельным функциям.\n\n```javascript\n// Complexity: 1\nconst sum = (a, b) => a + b\nsum(1, 3) // 4\n\n// Complexity: 2\nconst abs = n => (n >= 0 ? n : -n)\n\nabs(10) // 10\nabs(-3) // 3\n```\n\nВ примере выше у функции `sum` цикломатическая сложность равна единице, а у функции `abs` — двойке, так как она содержит ветвление, а значит два независимых пути выполнения.\n\nЧем больше возможных путей выполнения, тем сложнее функцию понять, отладить и модифицировать. Очевидно, что, с одной стороны, функции нужно дробить, а с другой — описывать логику программы так, чтобы не появлялись лишние пути. Даже опытные разработчики часто сталкиваются с этой проблемой.\n\nЛинтеры многих языков измеряют показатель сложности и сигнализируют, если он, скажем, больше 5 для одной функции.\n\n## Guard Expression\n\nПодход, который мы изучим, также называемый «паттерном», помогает лучше структурировать функцию и иногда сократить цикломатическую сложность. Рассмотрим пример:\n\n```javascript\nconst f = (age, sex) => {\n if (age >= 18) {\n if (sex === 'male') {\n return 'yes'\n }\n if (sex === 'female') {\n return 'no'\n }\n }\n\n return null\n}\n```\n\nВ этой функции вам все должно быть знакомо. Она принимает на вход возраст и пол. Для людей старше 18 в зависимости от пола возвращает строчку \"yes\" или \"no\". Для всех остальных — \"null\". В целом, с этой функцией все нормально, но кое-что можно улучшить.\n\nУсловие \"вернуть null, если младше 18 лет\" гораздо более простое и очевидное. Оно не подразумевает дальнейшего разветвления и сформулировано просто. Этим можно воспользоваться и произвести **рефакторинг** (улучшение работающего кода без изменения функциональности) таким образом, чтобы это условие отрабатывало первым.\n\n```javascript\nconst f = (age, sex) => {\n if (age < 18) {\n return null\n }\n\n if (sex === 'male') {\n return 'yes'\n }\n\n if (sex === 'female') {\n return 'no'\n }\n}\n```\n\nОбратите внимание на то, что уровень вложенности понизился. Основная логика находится вне условных конструкций. В такой реализации функции сложнее ошибиться: все, что пишется ниже _guard expression_ (первая проверка в данном случае), попадает под требование \"от 18 и старше\", а в первом примере код для этого условия нужно не забывать вставить внутрь соответствующего условия.\n\nНам уже знаком такой подход. Терминальные условия в рекурсиях выглядят точно так же.\n\nВ будущих практиках и в реальной жизни он встречается повсеместно. Используйте его осознанно и понижайте энтропию.\n"},"lessonMember":null,"courseMember":null,"course":{"start_lesson":{"exercise":null,"units":[{"id":2026,"name":"theory","url":"/courses/js-functions-hard-way/lessons/intro/theory_unit"}],"links":[],"ordered_units":[{"id":2026,"name":"theory","url":"/courses/js-functions-hard-way/lessons/intro/theory_unit"}],"id":976,"slug":"intro","state":"approved","name":"Введение","course_order":100,"goal":"Знакомимся с целями и задачами курса, готовим окружение","self_study":null,"theory_video_provider":null,"theory_video_uid":null,"theory":"Функции — тот элемент языка, с которым вы чаще всего будете иметь дело в будущем. В JavaScript они повсюду. И хотя вы уже научились создавать и использовать их, настоящая мощь функций раскроется в курсе [JS: коллекции](https://ru.hexlet.io/courses/js_collections), когда вы пройдете весь необходимый для этого материал. В дальнейшем при работе с асинхронным кодом вам понадобится мастерское владение функциями, так как на этом этапе от их количества начнет рябить в глазах.\n\nНиже рассмотрим пример, в котором нет ни одного нового синтаксического элемента, но если ваш опыт программирования ограничивается парой начальных курсов Хекслета, вы вряд ли сможете его понять:\n\n```javascript\nconst f = (x = 5) => y => x + y(3)\nf()(x => 7 + x) // 15\n```\n\nБуквально несколько строк, но очень высокая плотность кода. К концу курса вы сможете не только понять этот код, но и научитесь так писать. Для этого нужно соблюсти несколько условий:\n\n* Практически каждый курс на Хекслете содержит дополнительные задания (челленджи), которые помогают закрепить пройденный материал. Их нужно проходить, чтобы набить руку. К [курсу JS: Массивы](https://ru.hexlet.io/courses/js-arrays) таких задач довольно много, поэтому рекомендуем остановиться и пойти выполнить хотя бы штук 5, если вы до сих пор этого не сделали.\n* Привыкайте к новому синтаксису функций, даже если сейчас сложно. Уверяю вас, это всего лишь дело привычки. Хекслет не просто дает новые знания, но и старается формировать хорошие привычки.\n* Рекурсия станет центральной темой в ближайших нескольких курсах. Если у вас возникли сложности с ней, то самое время их победить. Попробуйте пройти челленджи [курса введение в программирование](https://ru.hexlet.io/courses/introduction_to_programming), используя только рекурсию, или попросите помощи в нашем комьюнити.\n* Ни в коем случае не двигайтесь вперед, пока не поняли тот урок, который проходите. Вероятность того, что вы поймете его потом, крайне мала. Скорее всего все станет еще сложнее, так как каждый следующий урок использует знания предыдущего. Если вам что-то непонятно, пишите в «Вопросы и ответы», и мы поможем вам продвинуться.\n\nТемы, которые мы рассмотрим в рамках этого курса:\n\n* Значение по умолчанию\n* Функции как объекты первого рода\n* Функции высшего порядка\n* Сложность функции\n* Частичное применение\n* Каррирование\n\nПараллельно с курсом рекомендуем посматривать в Википедию и знакомиться с соответствующими понятиями.\n\nПрактика в этом курсе с одной стороны достаточно простая и короткая, но порой мозговыносящая, так как придется жонглировать функциями в совершенно необычной форме. Она по-прежнему в основном ориентирована на арифметические операции, так как ваш текущий багаж знаний не позволяет рассматривать более сложные и интересные примеры, но это продлится недолго — уже со следующего курса мы переключимся на них.\n"},"id":151,"slug":"js-functions-hard-way","challenges_count":3,"name":"JS: Функциональное программирование","allow_indexing":true,"state":"approved","course_state":"finished","pricing_type":"paid","description":"На этом курсе вы изучите основы функционального программирования в JavaScript. Вы узнаете, что такое функции первого порядка. Вы научитесь уменьшать сложность функций и поймете, как функции ведут себя в составных выражениях. Вы освоите работу с механизмом замыканий, возвратом функций из функций, каррированием и частичным применением. Знания из этого курса помогут проектировать лаконичные и эффективные программы, отделяя побочные эффекты от чистого кода.","kind":"additional","updated_at":"2026-01-20T11:39:08.643Z","language":"javascript","duration_cache":39300,"skills":["Оценивать сложность функций и упрощать их код","Продвинутому использованию замыканий","Использовать композицию функций для решения реальных задач"],"keywords":["guard expression","основы функционального программирования","выражения и инструкции"],"lessons_count":9,"cover":"https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6NjEwMCwicHVyIjoiYmxvYl9pZCJ9fQ==--8a19418dd689b3f227e6674ecd168dfacaea7c89/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJqcGciLCJyZXNpemVfdG9fZmlsbCI6WzYwMCw0MDBdfSwicHVyIjoidmFyaWF0aW9uIn19--39ba06fa99226096df9fc6bb31f84e1d29ea98e9/image.png"},"recommendedLandings":[{"stack":{"id":20,"slug":"js-sicp","title":"СИКП на JS","audience":"for_programmers","start_type":"anytime","pricing_model":"subscription","priority":"medium","kind":"track","state":"published","stack_state":"finished","order":4050,"duration_in_months":1},"id":28,"slug":"js-sicp","title":"СИКП на JS","subtitle":"Навык понимать программы на фундаментальном уровне, уверенно проходить собеседования и решать сложные задачи","subtitle_for_lists":"Навык фундаментального программирования","locale":"ru","current":true,"duration_in_months_text":"1 месяц","stack_slug":"js-sicp","price_text":"от 3 900 ₽","duration_text":"1 месяц","cover_list_variant":"https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6Mzc2MCwicHVyIjoiYmxvYl9pZCJ9fQ==--9348098e4053d798b6f34bee4ef66947540261e4/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Low%20code%20development-rafiki.png"}],"lessonMemberUnit":null,"accessToLearnUnitExists":false,"accessToCourseExists":false},"url":"/courses/js-functions-hard-way/lessons/guard-expression/theory_unit","version":"8f286f6358a90a7bef2263b3a6edf5a90a94fa42","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">JS: Функциональное программирование</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">Теория: Guard Expression</h1><script type="application/ld+json">{"@context":"https://schema.org","@type":"LearningResource","name":"Guard Expression","inLanguage":"ru","isPartOf":{"@type":"LearningResource","name":"JS: Функциональное программирование"},"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 class="paywalled m_d08caa0 mantine-Typography-root"><p>Одни функции устроены сложнее других. Иногда так происходит в силу объективных причин (необходимая сложность). Иногда — в силу особенностей писавшего ее программиста (случайная сложность). И хотя нельзя однозначно описать эту сложность, существуют способы, позволяющие хотя бы частично ее оценить.</p>
<h2 id="heading-2-1">Цикломатическая сложность</h2>
<p>Цикломатическая сложность — это структурная или топологическая мера сложности компьютерной программы, разработанная Томасом Дж. Маккейбом в 1976 году.</p>
<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">if</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">if</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>, и один — если <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">false</code>.</p>
<p><img style="--image-object-fit:contain;width:auto" class="m_9e117634 mantine-Image-root" src="/rails/active_storage/blobs/proxy/eyJfcmFpbHMiOnsiZGF0YSI6NjEwMiwicHVyIjoiYmxvYl9pZCJ9fQ==--662b43f9a2915590d757cc6289dae4c775570c53/complexity_1.png" alt="Цикломатическая сложность" loading="lazy"/></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">// Complexity: 1
const sum = (a, b) => a + b
sum(1, 3) // 4
// Complexity: 2
const abs = n => (n >= 0 ? n : -n)
abs(10) // 10
abs(-3) // 3</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">sum</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">abs</code> — двойке, так как она содержит ветвление, а значит два независимых пути выполнения.</p>
<p>Чем больше возможных путей выполнения, тем сложнее функцию понять, отладить и модифицировать. Очевидно, что, с одной стороны, функции нужно дробить, а с другой — описывать логику программы так, чтобы не появлялись лишние пути. Даже опытные разработчики часто сталкиваются с этой проблемой.</p>
<p>Линтеры многих языков измеряют показатель сложности и сигнализируют, если он, скажем, больше 5 для одной функции.</p>
<h2 id="heading-2-2">Guard Expression</h2>
<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 f = (age, sex) => {
if (age >= 18) {
if (sex === 'male') {
return 'yes'
}
if (sex === 'female') {
return 'no'
}
}
return null
}</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>В этой функции вам все должно быть знакомо. Она принимает на вход возраст и пол. Для людей старше 18 в зависимости от пола возвращает строчку "yes" или "no". Для всех остальных — "null". В целом, с этой функцией все нормально, но кое-что можно улучшить.</p>
<p>Условие "вернуть null, если младше 18 лет" гораздо более простое и очевидное. Оно не подразумевает дальнейшего разветвления и сформулировано просто. Этим можно воспользоваться и произвести <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">const f = (age, sex) => {
if (age < 18) {
return null
}
if (sex === 'male') {
return 'yes'
}
if (sex === 'female') {
return 'no'
}
}</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>guard expression</em> (первая проверка в данном случае), попадает под требование "от 18 и старше", а в первом примере код для этого условия нужно не забывать вставить внутрь соответствующего условия.</p>
<p>Нам уже знаком такой подход. Терминальные условия в рекурсиях выглядят точно так же.</p>
<p>В будущих практиках и в реальной жизни он встречается повсеместно. Используйте его осознанно и понижайте энтропию.</p></div><div style="margin-block:var(--mantine-spacing-xl)" class=""><h2 style="--title-fw:var(--mantine-h2-font-weight);--title-lh:var(--mantine-h2-line-height);--title-fz:var(--mantine-h2-font-size);margin-bottom:var(--mantine-spacing-md)" class="m_8a5d1357 mantine-Title-root" data-order="2">Рекомендуемые программы</h2><style data-mantine-styles="inline">.__m__-_R_2mremqrdub_{--carousel-slide-gap:var(--mantine-spacing-xs);--carousel-slide-size:70%;}@media(min-width: 36em){.__m__-_R_2mremqrdub_{--carousel-slide-gap:var(--mantine-spacing-xl);--carousel-slide-size:50%;}}</style><div style="--carousel-control-size:calc(2.5rem * var(--mantine-scale));--carousel-controls-offset:var(--mantine-spacing-sm);margin-bottom:var(--mantine-spacing-lg);padding-block:var(--mantine-spacing-sm);background:var(--app-color-surface)" class="m_17884d0f mantine-Carousel-root responsiveClassName" data-orientation="horizontal" data-include-gap-in-size="true"><div class="m_39bc3463 mantine-Carousel-controls" data-orientation="horizontal"><button class="mantine-focus-auto m_64f58e10 mantine-Carousel-control m_87cf2631 mantine-UnstyledButton-root" type="button" data-inactive="true" data-type="previous" tabindex="-1"><svg viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg" style="transform:rotate(90deg);width:calc(1rem * var(--mantine-scale));height:calc(1rem * var(--mantine-scale));display:block"><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></button><button class="mantine-focus-auto m_64f58e10 mantine-Carousel-control m_87cf2631 mantine-UnstyledButton-root" type="button" data-inactive="true" data-type="next" tabindex="-1"><svg viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg" style="transform:rotate(-90deg);width:calc(1rem * var(--mantine-scale));height:calc(1rem * var(--mantine-scale));display:block"><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></button></div><div class="m_a2dae653 mantine-Carousel-viewport" data-type="media"><div class="m_fcd81474 mantine-Carousel-container __m__-_R_2mremqrdub_" data-orientation="horizontal"><div class="m_d98df724 mantine-Carousel-slide" data-orientation="horizontal"><div tabindex="0" style="cursor:pointer;height:100%"><a style="text-decoration:none" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/programs/js-sicp?promo_name=programs_list&promo_position=course&promo_creative=catalog_card&promo_type=card" target="_blank"><div style="height:100%" class="m_e615b15f mantine-Card-root m_1b7284a3 mantine-Paper-root" data-with-border="true"><div style="--group-gap:calc(0.25rem * var(--mantine-scale));--group-align:center;--group-justify:flex-start;--group-wrap:nowrap" class="m_4081bf90 mantine-Group-root"><span style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">1 месяц</span><span class="mantine-focus-auto m_b6d8b162 mantine-Text-root">·</span><span style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Для продвинутых</span></div><p style="margin-bottom:var(--mantine-spacing-sm);font-size:var(--mantine-font-size-h5);font-weight:bold" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">СИКП на JS</p><p class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Навык фундаментального программирования</p><div style="margin-top:auto" class=""><div class="m_4451eb3a mantine-Center-root"><img style="opacity:0.8;width:70%" class="m_9e117634 mantine-Image-root mantine-visible-from-xs" src="https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6Mzc2MCwicHVyIjoiYmxvYl9pZCJ9fQ==--9348098e4053d798b6f34bee4ef66947540261e4/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Low%20code%20development-rafiki.png" alt="СИКП на JS" loading="eager"/></div><div style="--group-gap:var(--mantine-spacing-md);--group-align:end;--group-justify:space-between;--group-wrap:wrap;margin-top:var(--mantine-spacing-xs)" class="m_4081bf90 mantine-Group-root"><p style="font-size:var(--mantine-font-size-xl)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">от 3 900 ₽</p><p style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Посмотреть →</p></div></div></div></a></div></div><div class="m_d98df724 mantine-Carousel-slide" data-orientation="horizontal"><div tabindex="0" style="cursor:pointer;height:100%"><a style="text-decoration:none" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/courses?promo_name=programs_list&promo_position=course&promo_creative=catalog_card&promo_type=card"><div style="height:100%" class="m_e615b15f mantine-Card-root m_1b7284a3 mantine-Paper-root" data-with-border="true"><h2 style="--title-fw:var(--mantine-h2-font-weight);--title-lh:var(--mantine-h2-line-height);--title-fz:var(--mantine-h2-font-size);margin-bottom:var(--mantine-spacing-md);font-size:var(--mantine-font-size-h3)" class="m_8a5d1357 mantine-Title-root" data-order="2" data-responsive="true">Каталог</h2><p style="margin-bottom:auto" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Полный список доступных курсов по разным направлениям</p><div style="margin-top:auto" class=""><div class="m_4451eb3a mantine-Center-root"><img style="opacity:0.8;width:70%" class="m_9e117634 mantine-Image-root mantine-visible-from-xs" src="/vite/assets/development-BVihs_d5.png" alt="Orientation"/></div></div></div></a></div></div></div></div></div></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/js-functions-hard-way/lessons/guard-expression/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 / 9</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/js-functions-hard-way/lessons/guard-expression/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-Bukl1lYy.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-BrRXra1y.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>