<!DOCTYPE html>
<html class="h-100" data-bs-theme="light" data-mantine-color-scheme="light" lang="ru" prefix="og: https://ogp.me/ns#">
<head>
<meta content="width=device-width, initial-scale=1.0" name="viewport">
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<link crossorigin="true" href="https://cdn.hexlet.io" rel="preconnect">
<link href="https://mc.yandex.ru" rel="preconnect">
<meta content="aa2vrdtq64dub8knuf83lwywit311w" name="facebook-domain-verification">
<link href="/favicon.ico" rel="icon" sizes="any">
<link href="/favicon.svg" rel="icon" type="image/svg+xml">
<link href="/apple-touch-icon.png" rel="apple-touch-icon">
<link href="/manifest.webmanifest" rel="manifest">
<script>
//<![CDATA[
window.gon={};gon.ym_counter="25559621";gon.is_bot=true;gon.applications={};gon.current_user={"id":null,"last_viewed_notification_id":null,"email":null,"state":null,"first_name":"","last_name":"","created_at":"2026-02-26 17:17:49 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="Q2sWZwGWlBwP59gaGqqwbrldcT7QVyJXkkX8pkeRtEusut1Q8-g5fLmk_IIWpUAZeVRclNhg3PUvpWbyFZZTJQ";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>Операция rest | JS: Коллекции</title>
<meta name="description" content="Операция rest / JS: Коллекции: Рассматриваем интересную особенность, которая позволяет передавать разное количество параметров в функцию">
<link rel="canonical" href="https://ru.hexlet.io/courses/js-collections/lessons/rest_operator/theory_unit">
<meta name="robots" content="noarchive">
<meta property="og:title" content="Операция rest">
<meta property="og:title" content="JS: Коллекции">
<meta property="og:description" content="Операция rest / JS: Коллекции: Рассматриваем интересную особенность, которая позволяет передавать разное количество параметров в функцию">
<meta property="og:url" content="https://ru.hexlet.io/courses/js-collections/lessons/rest_operator/theory_unit">
<meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="6lM5_l_kLoQwLok0MTV5h1kMNqW6JTlDAq31Cf6iQZ0FgvLJrZqD5IZtraw9OonwmQUbD7ISx-G_TW9drKWm8w" />
<script src="/vite/assets/inertia-INZxX8jp.js" crossorigin="anonymous" type="module"></script><link rel="modulepreload" href="/vite/assets/chunk-DsPFFUou.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/preload-helper-BJ4cLWpC.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/init-nkZBEvfU.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/ahoy-DrlRQ-1D.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/analytics-6pOtQ3OW.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/ErrorFallbackBlock-naDSYSy9.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Surface-DL2bpZA-.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/gon-D3e4yh1x.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/mantine-CGMYrt2Y.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/utils-DRqSHbQE.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/routes-CCH8ilKF.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/extends-C-EagtpE.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/inheritsLoose-BBd-DCVI.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/objectWithoutPropertiesLoose-DRHXDhjp.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/index.esm-DAqKOkZ0.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Button-CGPUux8l.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/CloseButton-D1euiPao.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Group-BX48WcuU.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Loader-BQEY8g6v.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Modal-Cy3HByv7.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/OptionalPortal-1Hza5P2w.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Stack-CtjJzfw4.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Textarea-Ck64llAy.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Box-B5-OOzBf.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/DirectionProvider-Dc9zdUke.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/events-DJQOhap0.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/use-reduced-motion-D2owz4wa.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/use-disclosure-zKtK5W1r.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/use-hotkeys-Cnc_Rwkb.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/random-id-DOQyszCZ.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/notifications.store-C-3AFSMn.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/exports-C_MrNx_T.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/axios-BEvgo0ym.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/dayjs.min-BkKovM-s.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/i18next-BlSq9s7B.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/client-U9M77rxp.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-dom-DaLxUz_h.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/useTranslation-Bx1Cdrkz.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/compiler-runtime-6XxiPFnt.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/jsx-runtime-CwjcCKJi.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-CkL4ZRHB.js" as="script" crossorigin="anonymous">
<link rel="stylesheet" href="/vite/assets/application-BqhCP46M.js" />
<script src="/vite/assets/application-Df9RExpe.js" crossorigin="anonymous" type="module"></script><link rel="modulepreload" href="/vite/assets/chunk-DsPFFUou.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/autocomplete-VMNbxKGl.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/routes-CCH8ilKF.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/createPopper-C3aM9r1M.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/js.cookie-D1-O8zkX.js" as="script" crossorigin="anonymous"><link rel="stylesheet" href="/vite/assets/application-C8HjmMaq.css" media="screen" />
<script>
window.ym = function(){(ym.a=ym.a||[]).push(arguments)};
window.addEventListener('load', function() {
setTimeout(function() {
ym.l = 1*new Date();
ym(window.gon.ym_counter, "init", {
clickmap: true,
trackLinks: true,
accurateTrackBounce: true,
webvisor: true
});
// Загружаем скрипт
var k = document.createElement('script');
k.async = 1;
k.src = 'https://mc.yandex.ru/metrika/tag.js';
document.head.appendChild(k);
ym(window.gon.ym_counter, 'getClientID', function(clientID) {
window.ymClientId = clientID;
});
}, 1500);
});
</script>
<!-- Google Tag Manager - deferred -->
<script>
// dataLayer stub сразу — пуши работают до загрузки скрипта
window.dataLayer = window.dataLayer || [];
// Сам скрипт — отложенно после load
window.addEventListener('load', function() {
setTimeout(function() {
dataLayer.push({'gtm.start': new Date().getTime(), event: 'gtm.js'});
var j = document.createElement('script');
j.async = true;
j.src = 'https://www.googletagmanager.com/gtm.js?id=GTM-WK88TH';
document.head.appendChild(j);
}, 1500);
});
</script>
<!-- End Google Tag Manager -->
</head>
<body>
<noscript>
<div>
<img alt="" src="https://mc.yandex.ru/watch/25559621" style="position:absolute; left:-9999px;">
</div>
</noscript>
<header class="sticky-top bg-body">
<nav class="navbar navbar-expand-lg">
<div class="container-xxl">
<a class="navbar-brand" href="/"><img alt="Логотип Хекслета" height="24" src="https://ru.hexlet.io/vite/assets/logo_ru_light-BpiEA1LT.svg" width="96">
</a><button aria-controls="collapsable" aria-expanded="false" aria-label="Меню" class="navbar-toggler border-0 mb-0 mt-1" data-bs-target="#collapsable" data-bs-toggle="collapse">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="collapsable">
<ul class="navbar-nav mb-lg-0 mt-lg-1">
<li class="nav-item dropdown">
<button aria-haspopup class="btn nav-link" data-bs-toggle="dropdown" type="button">
Все курсы
<span class="bi bi-chevron-down align-middle ms-1"></span>
</button>
<ul class="dropdown-menu">
<li>
<a class="dropdown-item d-flex py-2" href="/courses"><div class="fw-bold me-auto">Все что есть</div>
<div class="text-muted">117</div>
</a></li>
<li>
<hr class="dropdown-divider">
</li>
<li class="dropdown-item">
<b>Популярные категории</b>
</li>
<li>
<a class="dropdown-item py-2" href="/courses_devops">Курсы по DevOps
</a></li>
<li>
<a class="dropdown-item py-2" href="/courses_data_analytics">Курсы по аналитике данных
</a></li>
<li>
<a class="dropdown-item py-2" href="/courses_programming">Курсы по программированию
</a></li>
<li>
<a class="dropdown-item py-2" href="/courses_testing">Курсы по тестированию
</a></li>
<li>
<hr class="dropdown-divider">
</li>
<li class="dropdown-item">
<b>Популярные курсы</b>
</li>
<li>
<a class="dropdown-item py-2" href="/programs/devops-engineer-from-scratch">DevOps-инженер с нуля
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/go">Go-разработчик
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/java">Java-разработчик
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/python">Python-разработчик
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/qa-auto-engineer-java">Автоматизатор тестирования на Java
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/data-analytics">Аналитик данных
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/frontend">Фронтенд-разработчик
</a></li>
</ul>
</li>
<li class="nav-item dropdown">
<button aria-haspopup class="btn nav-link" data-bs-toggle="dropdown" type="button">
О Хекслете
<span class="bi bi-chevron-down align-middle"></span>
</button>
<ul class="dropdown-menu bg-body">
<li>
<a class="dropdown-item py-2" href="/pages/about">О нас
</a></li>
<li>
<a class="dropdown-item py-2" href="/blog">Блог
</a></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://special.hexlet.io/hse-research" role="button">Результаты (Исследование)
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://career.hexlet.io" role="button">Хекслет Карьера
</span></li>
<li>
<a class="dropdown-item py-2" href="/testimonials">Отзывы студентов
</a></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://t.me/hexlet_help_bot" role="button">Поддержка (В ТГ)
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://special.hexlet.io/referal-program/?promo_creative=priglasite-druzei&promo_name=referal-program&promo_position=promo_position&promo_start=010724&promo_type=link" role="button">Реферальная программа
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://special.hexlet.io/certificate" role="button">Подарочные сертификаты
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://hh.ru/employer/4307094" role="button">Вакансии
</span></li>
<li>
<span class="dropdown-item d-flex external-link" rel="noopener noreferrer nofollow" data-href="https://b2b.hexlet.io" data-target="_blank" role="button">Компаниям
</span></li>
<li>
<span class="dropdown-item d-flex external-link" rel="noopener noreferrer nofollow" data-href="https://hexly.ru/" data-target="_blank" role="button">Колледж
</span></li>
<li>
<span class="dropdown-item d-flex external-link" rel="noopener noreferrer nofollow" data-href="https://hexlyschool.ru/" data-target="_blank" role="button">Частная школа
</span></li>
</ul>
</li>
<li><a class="nav-link" href="/subscription/new">Подписка</a></li>
</ul>
<ul class="navbar-nav flex-lg-row align-items-lg-center gap-2 ms-auto">
<li>
<a class="nav-link" aria-label="Переключить тему" href="/theme/switch?new_theme=dark"><span aria-hidden="true" class="bi bi-moon"></span>
</a></li>
<li>
<span data-target="_self" class="nav-link external-link" data-href="/u/new" role="button"><span>Регистрация</span>
</span></li>
<li>
<span data-target="_self" class="nav-link external-link" data-href="https://ru.hexlet.io/session/new" role="button"><span>Вход</span>
</span></li>
</ul>
</div>
</div>
</nav>
</header>
<div class="x-container-xxxl">
</div>
<main class="mb-6 min-vh-100 h-100">
<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-26T17:17:49.303Z","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":"O5sx32UHB18FEuJHhOY2Vk8b5GPizvGO7T9F9WKPXIvUSvrol3mqP7NRxt-I6cYhjxLJyer5DyxQ39-hMIi75Q","topics":[{"id":11689,"title":"Кирилл здравствуйте, будьте добры взгляните на решение https://ru.hexlet.io/code_reviews/29077#file-0, код работает но от решения учителя отличается сильно.\nСпасибо ","plain_title":"Кирилл здравствуйте, будьте добры взгляните на решение https://ru.hexlet.io/code_reviews/29077#file-0, код работает но от решения учителя отличается сильно. Спасибо ","creator":{"public_name":"Дмитрий Сибиряков","id":147425,"is_tutor":false},"comments":[{"creator":{"public_name":"Kirill Mokevnin","id":1,"is_tutor":false},"id":24284,"body":"Честно говоря я не могу разобраться в таких длинных строчках с кучей вызовов. Всегда лучше промежуточные вычисления записывать в константы.","topic_id":11689}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Операция rest","entity_url":null,"active":true}},{"id":19927,"title":"Добрый день, в тестах появляется ошибка, правильно ли я понимаю, что ошибка связана с тем что map возвращает массив с функцией, а по условию должна возвращаться одна функция ?\n```\n where(...arg) {\n return arg.map(item => {\n if (typeof item === 'function') {\n return this.build(coll => coll.filter(item))\n } return this.build(coll => coll.every(Object.keys(item)))\n })\n }\n```\n```\n TypeError: coll.where(...).where is not a function\n\n 20 | const result = coll\n 21 | .where(car => car.brand === 'kia')\n > 22 | .where(car => car.year > 2011);\n | ^\n 23 | \n 24 | expect(result.toArray()).toEqual([cars[2], cars[4]]);\n 25 | \n\n at Object.where (__tests__/enumerable.test.js:22:8)\n```","plain_title":"Добрый день, в тестах появляется ошибка, правильно ли я понимаю, что ошибка связана с тем что map возвращает массив с функцией, а по условию должна возвращаться одна функция ? where(...arg) { return arg.map(item => { if (typeof item === 'function') { return this.build(coll => coll.filter(item)) } return this.build(coll => coll.every(Object.keys(item))) }) } ``` TypeError: coll.where(...).where is not a function 20 | const result = coll 21 | .where(car => car.brand === 'kia') > 22 | .where(car => car.year > 2011); | ^ 23 | 24 | expect(result.toArray()).toEqual([cars[2], cars[4]]); 25 | at Object.where (__tests__/enumerable.test.js:22:8) ","creator":{"public_name":"Дмитрий Струнгарь","id":138989,"is_tutor":false},"comments":[{"creator":{"public_name":"Илья Токарев","id":76797,"is_tutor":false},"id":42055,"body":"Нет, по условию должен возвращаться экземпляр Enumerable. Как вы предыдущие упражнения прошли? посмотрите внимательно на where из прошлых уроков.","topic_id":19927},{"creator":{"public_name":"Дмитрий Струнгарь","id":138989,"is_tutor":false},"id":42201,"body":"ага, понял, что-то не то возвращается, спасибо за помощь","topic_id":19927},{"creator":{"public_name":"Александр О.","id":61806,"is_tutor":false},"id":42167,"body":"> в предыдущих курсах работали с функцией build которая возвращает Enumerable\n\nДа, вызов build возвращает новый экземпляр Enumerable. Но ваша реалазация where не возвращает экземпляр Enumerable.","topic_id":19927},{"creator":{"public_name":"Илья Токарев","id":76797,"is_tutor":false},"id":42057,"body":"Вы возвращаете массив объектов Enumerable.","topic_id":19927},{"creator":{"public_name":"Дмитрий Струнгарь","id":138989,"is_tutor":false},"id":42056,"body":"мы же в предыдущих курсах работали с функцией build которая возвращает Enumerable, т.е я совсем не в ту степь копать начал?","topic_id":19927}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Операция rest","entity_url":null,"active":true}},{"id":19763,"title":"Не правильнее ли будет писать так `// removed`? Мы же сравниваем значения, а не ключи.","plain_title":"Не правильнее ли будет писать так // removed? Мы же сравниваем значения, а не ключи. ","creator":{"public_name":"Анна Дудек","id":130514,"is_tutor":false},"comments":[{"creator":{"public_name":"Илья Токарев","id":76797,"is_tutor":false},"id":41768,"body":"Значения, которые берутся по ключу key, взятому из массива keys. Мы сравниваем значения, но перебираем то именно ключи.\n\nelement[key] = value;","topic_id":19763},{"creator":{"public_name":"Александр О.","id":61806,"is_tutor":false},"id":41819,"body":"В коде тоже сравниваются значения, а не ключи. Доступ к значениям осуществляется через ключи.","topic_id":19763}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Операция rest","entity_url":null,"active":true}},{"id":33540,"title":"Выполнил первое условие \n\n```\nif(typeof item === 'function') {\n return this.build((coll) => coll.filter(item));\n }\n```\nно что делать, если item это объект ? \nИ для чего нам функция every ?\n\nЕсли это объект, то мы должны применить функцию filter ко всему списку, для чего же все таки every ?","plain_title":"Выполнил первое условие if(typeof item === 'function') { return this.build((coll) => coll.filter(item)); } но что делать, если item это объект ? И для чего нам функция every ? ","creator":{"public_name":"Alexander","id":233178,"is_tutor":false},"comments":[{"creator":{"public_name":"Stanislav Dzisiak","id":212236,"is_tutor":true},"id":73168,"body":"**Alexander**, привет!\n\nОтлично, что вы справились с упражнением!","topic_id":33540},{"creator":{"public_name":"Alexander","id":233178,"is_tutor":false},"id":73117,"body":"Разобрался, ошибка была в том, что возвращает map. Для функций все работает правильно, теперь надо сделать для object\n\nРешил. Что я могу сказать...надо больше практики (","topic_id":33540},{"creator":{"public_name":"Alexander","id":233178,"is_tutor":false},"id":73113,"body":"Посмотрите, пожалуйста, в правильном направлении иду ? https://ru.hexlet.io/code_reviews/164395\n\nПолучаю TypeError: result.toArray is not a function, это из-за того, что не могу сделать вторую часть ? ","topic_id":33540}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Операция rest","entity_url":null,"active":true}},{"id":20954,"title":"Уже пару дней сижу над задачей и пока решение не дошло до меня. Конкретный вопрос: почему данный код\n\n`// removed`\n\nне отрабатывает даже для единственной функции? Я проэкспериментировал на repl.it. В моем понимании при вызове метода ```where``` в нынешнем его виде и передаче туда одной функции должен вернуться массив из, соответсвенно, одной функции, который далее передается в ```build```. Отладочная печать показала, что в ```newElements``` оказывается массив из одной функции как я и ожидаю. Однако на репле получаю ошибку:\n\nTypeError: this.getProcessedCollection(...).slice is not a function\n at Enumerable.toArray (evalmachine.<anonymous>:38:42)\n at evalmachine.<anonymous>:56:20\n at Script.runInContext (vm.js:74:29)\n at Object.runInContext (vm.js:182:6)\n at evaluate (/run_dir/repl.js:133:14)\n at ReadStream.<anonymous> (/run_dir/repl.js:116:5)\n at ReadStream.emit (events.js:180:13)\n at addChunk (_stream_readable.js:274:12)\n at readableAddChunk (_stream_readable.js:261:11)\n at ReadStream.Readable.push (_stream_readable.js:218:10)","plain_title":"Уже пару дней сижу над задачей и пока решение не дошло до меня. Конкретный вопрос: почему данный код // removed не отрабатывает даже для единственной функции? Я проэкспериментировал на repl.it. В моем понимании при вызове метода where в нынешнем его виде и передаче туда одной функции должен вернуться массив из, соответсвенно, одной функции, который далее передается в build. Отладочная печать показала, что в newElements оказывается массив из одной функции как я и ожидаю. Однако на репле получаю ошибку: TypeError: this.getProcessedCollection(...).slice is not a function at Enumerable.toArray (evalmachine.:38:42) at evalmachine.:56:20 at Script.runInContext (vm.js:74:29) at Object.runInContext (vm.js:182:6) at evaluate (/rundir/repl.js:133:14) at ReadStream. (/rundir/repl.js:116:5) at ReadStream.emit (events.js:180:13) at addChunk (streamreadable.js:274:12) at readableAddChunk (streamreadable.js:261:11) at ReadStream.Readable.push (streamreadable.js:218:10) ","creator":{"public_name":"Валерий Серёгин","id":174277,"is_tutor":false},"comments":[{"creator":{"public_name":"Валерий Серёгин","id":174277,"is_tutor":false},"id":44370,"body":"Решил. Пара замечаний:\n1. Сообщение Анны Дудек от 10 октября лучше было бы удалить, т. к. слишком жирный спойлер.\n2. В строчке задания **Извлечь ключи из объекта можно функцией Object.keys** лучше переписать как **Извлечь ключи из объекта можно функцией Object.keys(obj)**","topic_id":20954},{"creator":{"public_name":"Валерий Серёгин","id":174277,"is_tutor":false},"id":44349,"body":"Весь код с репла \n\n`// removed`","topic_id":20954},{"creator":{"public_name":"Валерий Серёгин","id":174277,"is_tutor":false},"id":44354,"body":"Понял, что единственная функция, о которой я веду речь, это функция-предикат, а не функция-преобразователь. Как следствие вопрос по функциям отпал. Сейчас думаю над объектами.","topic_id":20954},{"creator":{"public_name":"Александр О.","id":61806,"is_tutor":false},"id":44413,"body":"Добрый день!\n\nЗд0рово, что удалось справиться!\n\n> Пара замечаний:\n\n1. Удалил спойлер. Спасибо!\n2. Так не лучше. `Object.keys` - это функция. `Object.keys(obj)` - это пример вызова функции. Вы, на уровне этого курса, уже достаточно большие, чтобы разобраться в этом.\n","topic_id":20954}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Операция rest","entity_url":null,"active":true}},{"id":16847,"title":"Прошу прощения за возможный спойлер ниже.\nНе могу понять прошу помощи.\n1) правильно ли я написал result = ...? не уверен работающая ли это конструкция?\nесли item в map функция, то срабатывает functions, если нет то objects\n2) правильно ли я написал predicat ? подозреваю что не правильно. В тестах возвращает весь массив объектов.\n\n`// removed`","plain_title":"Прошу прощения за возможный спойлер ниже. Не могу понять прошу помощи. 1) правильно ли я написал result = ...? не уверен работающая ли это конструкция? если item в map функция, то срабатывает functions, если нет то objects 2) правильно ли я написал predicat ? подозреваю что не правильно. В тестах возвращает весь массив объектов. // removed ","creator":{"public_name":"Alexander Suleymanov","id":92508,"is_tutor":false},"comments":[{"creator":{"public_name":"Александр О.","id":61806,"is_tutor":false},"id":35686,"body":"Добрый день!\n\n`map` принимает на вход функцию, вы же передали не функцию\n\n","topic_id":16847},{"creator":{"public_name":"Alexander Suleymanov","id":92508,"is_tutor":false},"id":35695,"body":"!!!!АААА\nСделал. Спасибо Александр большое!","topic_id":16847},{"creator":{"public_name":"Александр О.","id":61806,"is_tutor":false},"id":35698,"body":"Поздравляю! :)","topic_id":16847}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Операция rest","entity_url":null,"active":true}},{"id":18431,"title":"Задание я понял, алгоритм решения в принципе тоже\n. Мапом прохожу по каждому элементу массива (rest), переданного в where.\nЕсли елемет - функция, то заношу функцию в оперейшн.\nЕсли объект, то извлекаю из него ключ для сортировки, добавляю в оперейшн.\n но не понял следующее:\n1.Для чего и где мы делаем every? Проверяем переданный в where массив на соответствие? А у нас в тестах вроде все соответствует.\n2.Предикаты это что? Функция, в которой мы проверяем тип элемента? Зачем делать специально эту функцию, ведь достаточно один иф написать","plain_title":"Задание я понял, алгоритм решения в принципе тоже . Мапом прохожу по каждому элементу массива (rest), переданного в where. Если елемет - функция, то заношу функцию в оперейшн. Если объект, то извлекаю из него ключ для сортировки, добавляю в оперейшн. но не понял следующее: 1.Для чего и где мы делаем every? Проверяем переданный в where массив на соответствие? А у нас в тестах вроде все соответствует. 2.Предикаты это что? Функция, в которой мы проверяем тип элемента? Зачем делать специально эту функцию, ведь достаточно один иф написать ","creator":{"public_name":"Иван Нор","id":151614,"is_tutor":false},"comments":[{"creator":{"public_name":"Иван Нор","id":151614,"is_tutor":false},"id":39402,"body":"ну так а как передать функцию в функции? )))","topic_id":18431},{"creator":{"public_name":"Иван Нор","id":151614,"is_tutor":false},"id":38951,"body":"Александр, все-таки не могу пока разобраться( \n```\nwhere(...theArgs) {\n return theArgs.slice().map((item) => {\n if (typeof item === 'function') {\n return this.build(coll => coll.filter(item));\n }\n return Object.keys(item).map(elem => this.build(coll => coll.filter(elem)));\n });\n }\n```\nвот мой код. а вывод тестов не понятен\n```\nTypeError: coll.where(...).where is not a function\n\n 20 | const result = coll\n 21 | .where(car => car.brand === 'kia')\n > 22 | .where(car => car.year > 2011);\n | ^\n 23 | \n 24 | expect(result.toArray()).toEqual([cars[2], cars[4]]);\n 25 | \n\nHexletLinq › #where 2\n\n TypeError: coll.where(...).where is not a function\n\n 42 | it('#where 2', () => {\n 43 | const result = coll.where(car => car.year < 2014)\n > 44 | .where(car => car.brand === 'kia', car => car.year > 2011);\n | ^\n 45 | \n 46 | expect(result.toArray()).toEqual([cars[4]]);\n 47 | });\n```\nwhere не функция, причем на предыдущей строчке код не падает.","topic_id":18431},{"creator":{"public_name":"Иван Нор","id":151614,"is_tutor":false},"id":38950,"body":"Вместо мапа для прохождения по theArgs лучше использовать foreach? Ведь мне не нужна новая коллекция, мне нужно только в очередь добавить функции фильтровки.\nВычисления делаются при вызове в тестах toArray, все как в прошлом задании?","topic_id":18431},{"creator":{"public_name":"Александр О.","id":61806,"is_tutor":false},"id":38985,"body":"> вот мой код\n\nВам надо понять, что именно хотите вернуть во второй инструкции `return`. Ведь в конечно счёте вызов `where` должен возвратить новый объект. А это сводится к правильному вызову функции `build` (так как это у вас реализовано с типом `function`).\n\nА сейчас в последней инструкции вашей функции генерится массив новых объектов. А ведь нужен один объект.","topic_id":18431},{"creator":{"public_name":"Александр О.","id":61806,"is_tutor":false},"id":39374,"body":"> когда я беру первый элемент theArgs - item - в нем содержится функция\n\nДа, если это функция, а не объект. Ведь передаваться может несколько типов занчений: либо фунции, либо объекты.\n\n> когда я делаю this.operations = this.operations.concat(coll => coll.filter(item)); то в operations попадает coll => coll.filter(item), а не содержимое item.\n\nВ массив попадает ровно то значение, какое вы передаёте в метод concat. Если в метод concat вы передаёте функцию `coll => coll.filter(item)`, то именно эта функция оказывается в массиве, как бы тривиально это не звучало. Т.е. здесь всё правильно выходит.","topic_id":18431},{"creator":{"public_name":"Александр О.","id":61806,"is_tutor":false},"id":38916,"body":"Иван, ситуация такова: если вы действительно понимаете задание и алгоритм решения - то пишите реализацию без оглядки на те вещи, которые сейчас вам непонятны. Будет хорошо, если вы сделаете код без функции every и предикатов, с другой стороны, в процессе решения вы, возможно, почувствуете, что именно их вам не хватает и поймёте суть подсказок. И всегда можете потом сравнить своё решение с учительским, сделав вывода, где получилось удачнее.\n\n> Предикаты это что? Функция, в которой мы проверяем тип элемента?\n\nФункция, делающая проверку и возвращающая логическое значение (true/false), например `car => car.year < 2013`","topic_id":18431},{"creator":{"public_name":"Иван Нор","id":151614,"is_tutor":false},"id":39369,"body":"Понял! спасибо за ответ! а как насчет моего предыдущего вопроса?\n> когда я беру первый элемент theArgs - item - в нем содержится функция, когда я делаю this.operations = this.operations.concat(coll => coll.filter(item)); то в operations попадает coll => coll.filter(item)\n\n, а не \n`coll => coll.filter(car=>car.year > 2010) //например`\nНе понимаю, почему item передается как текст или не пойми что. console.log печатает такой вывод:\n```\nconsole.log(this.operations.toString);\n// coll => coll.filter(item)\n```","topic_id":18431},{"creator":{"public_name":"Александр О.","id":61806,"is_tutor":false},"id":39436,"body":"> ну так а как передать функцию в функции? )))\n\nВот об этом вам надо подумать :) А так это выглядит как просьба показать решение.","topic_id":18431},{"creator":{"public_name":"Иван Нор","id":151614,"is_tutor":false},"id":38870,"body":"item.keys() - is not a function.\nитем - объект. Почему-то не берет из него массив ключей(((","topic_id":18431},{"creator":{"public_name":"Александр О.","id":61806,"is_tutor":false},"id":39356,"body":"> при вызове build разве мы можем передавать туда массив функций?\n\nДа можете, он присоединяется с помощью `concat`","topic_id":18431},{"creator":{"public_name":"Иван Нор","id":151614,"is_tutor":false},"id":39002,"body":"если я возвращаю новый объект(по аналогии с build), ошибка та же( \n```\nreturn new Enumerable(this.collection.slice(), this.operations.slice());\n```\n> Вам надо понять, что именно хотите вернуть во второй инструкции return.\n\nвторая инструкция return относится к мапу. я добавил строку с возвратом обьекта, уже после вызова мапа добавления всех функций в оперейшнс, но по-прежнему where is not a function","topic_id":18431},{"creator":{"public_name":"Иван Нор","id":151614,"is_tutor":false},"id":39462,"body":"так у меня затык в синтаксисе. я ведь понял задание, но не могу довести до конца свой вариант решения из-за того, что упускаю какую-то мелочь. Скажите хотя бы может тему из более ранних курсов. Как тут можно увидеть просьбу показать решение, я не понимаю.\n","topic_id":18431},{"creator":{"public_name":"Иван Нор","id":151614,"is_tutor":false},"id":39012,"body":"c выводом я разобрался, код изменил, where2 выполняется правильно. Но когда я беру первый элемент theArgs - item - в нем содержится функция, когда я делаю `this.operations = this.operations.concat(coll => coll.filter(item));`\nто в operations попадает `coll => coll.filter(item)`, а не содержимое item. Не понимаю, почему.\nи такой еще вопрос. при вызове build разве мы можем передавать туда массив функций? ","topic_id":18431},{"creator":{"public_name":"Иван Нор","id":151614,"is_tutor":false},"id":39009,"body":"```\nwhere(...theArgs) {\n theArgs.slice().forEach((item) => {\n if (typeof item === 'function') {\n this.operations.concat(coll => coll.filter(item));\n const stringOperations = this.operations.toString();\n }\n const keyArr = Object.keys(item);\n keyArr.forEach((elem) => {\n this.operations.concat(coll => coll.filter(car => car.elem));\n });\n });\n return new Enumerable(this.collection.slice(), this.operations.slice());\n }\n```\n\nя все-же вернусь к этому. Разобрался с возвратом в where, но фильтрацию не проводит. \nчтобы понять, где что-то идет не так, я делаю консоль.лог, но\n`console.log('operations -> '+this.operations.toString());`\nкуда ни засунь, печатает пустоту, хотя я делаю в коде вызов `this.operations.concat(coll => coll.filter(item));` что означает, что этот элемент должен добавиться в оперейшнс. Но ниже все так же пустота при выводе оперейшнс. Неправильный синтаксис toString? \n","topic_id":18431},{"creator":{"public_name":"Александр О.","id":61806,"is_tutor":false},"id":39539,"body":"> так у меня затык в синтаксисе. \n\nСформулируйте конкретнее свой вопрос.","topic_id":18431}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Операция rest","entity_url":null,"active":true}},{"id":8863,"title":"Любопытная задача. Решил. Пойду разбираться, как тут прикручивать every из подсказок, а то моё велорешение без неё работает.","plain_title":"Любопытная задача. Решил. Пойду разбираться, как тут прикручивать every из подсказок, а то моё велорешение без неё работает. ","creator":{"public_name":"Евгений Михайлов","id":132122,"is_tutor":false},"comments":[{"creator":{"public_name":"Kirill Mokevnin","id":1,"is_tutor":false},"id":17731,"body":"А главное что задача вполне реальная: http://knexjs.org/","topic_id":8863}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Операция rest","entity_url":null,"active":true}},{"id":23404,"title":"Потратил больше двух часов на решение задачи, прочитал все топики. В итоге расписал алгоритм по шагам, проверяя результаты каждого шага в консоли.\n\n```\nТо что every() используется внутри filter() не сразу дошло.\n```","plain_title":"Потратил больше двух часов на решение задачи, прочитал все топики. В итоге расписал алгоритм по шагам, проверяя результаты каждого шага в консоли. То что every() используется внутри filter() не сразу дошло. ","creator":{"public_name":"Степан Засименко","id":180096,"is_tutor":false},"comments":[{"creator":{"public_name":"Евгений Сверчков","id":125203,"is_tutor":false},"id":51855,"body":"оставьте задачу на следующий день. Ваше подсознание само найдет решение. ","topic_id":23404},{"creator":{"public_name":"Александр Иноземцев","id":189031,"is_tutor":false},"id":58954,"body":"**Магжан Сыдыков**, Для Вас возможно это так, как для меня, я ответил выше :)","topic_id":23404},{"creator":{"public_name":"Александр Иноземцев","id":189031,"is_tutor":false},"id":52409,"body":"Да, обычно так и бывает, как только сознание отпускает мыслительную хватку, бессознательное любезно выдает решение","topic_id":23404},{"creator":{"public_name":"Магжан Сыдыков","id":181574,"is_tutor":false},"id":58933,"body":"**Александр Иноземцев**, не все так просто, сначала необходимо приложить определенное количество усилий иначе прокрастинация не была бы собой.","topic_id":23404}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Операция rest","entity_url":null,"active":true}},{"id":4024,"title":"У меня ступор: не могу понять почему такая ошибка. \n```\n// removed\n```\nTypeError: Cannot read property 'where' of undefined\n```","plain_title":"У меня ступор: не могу понять почему такая ошибка. // removed TypeError: Cannot read property 'where' of undefined ``` ","creator":{"public_name":"Anton Shvab","id":46270,"is_tutor":false},"comments":[{"creator":{"public_name":"Anton Shvab","id":46270,"is_tutor":false},"id":6791,"body":"Я наверное не понял что вы имеете ввиду. Перед `elements` ведь стоит rest оператор, значит все что попадают на вход `where` попадает в массив. Для этого массива вызывается метод `forEach(helper`. Где `helper` - это ф-я, которая делает диспетчеризацию по типу элемента массива. ","topic_id":4024},{"creator":{"public_name":"Александр Шакун","id":23001,"is_tutor":false},"id":6765,"body":"Давайте начнем с начала. У нас в задании написано:\n```\nФункция может принимать любое количество параметров, каждый из которых может быть либо функцией, либо объектом.\n```\nа вы пишите\n```\nelements.forEach(helper)\n```\nисходя из чего можно сказать что ваша функция может принимать на вход только массив, потому что только у него есть метод `forEach`, соответственно, стоит начать с начала и переработать `where`. Давайте начнем с этого.","topic_id":4024},{"creator":{"public_name":"Александр Шакун","id":23001,"is_tutor":false},"id":6848,"body":"Да, вы правы. Тут у нас дело в другом.\nВ тесте есть вот такой код:\n```\n const result = coll\n .where(car => car.brand === 'kia')\n .where(car => car.year > 2011);\n```\nИ первые две строки выполняются как надо, но когда приходит время для \n```\n.where(car => car.year > 2011);\n```\nмы получаем ошибку \n```\nTypeError: Cannot read property 'where' of undefined\n```\nпотому что вот этот код \n```\n const result = coll\n .where(car => car.brand === 'kia')\n```\nвозвращает `undefined` потому что когда вы реализованом методе используете `elements.forEach(helper)` в итоге из метода возвращается `undefined` потому что собственно `forEach` возвращает `undefined`:\n>Метод forEach() выполняет функцию callback один раз для каждого элемента массива; в отличие от методов every() и some(), он всегда возвращает значение undefined.\n\nhttps://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach\n","topic_id":4024}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Операция rest","entity_url":null,"active":true}}],"lesson":{"exercise":{"id":478,"slug":"js_collections_rest_operator_exercise","name":null,"state":"active","kind":"exercise","language":"javascript","locale":"ru","has_web_view":false,"has_test_view":false,"reviewable":true,"readme":"## Enumerable.js\n\nРеализуйте метод `where()`, основываясь на следующем интерфейсе:\n\nФункция может принимать любое количество параметров, каждый из которых может быть либо функцией, либо объектом. Для функций должна осуществляться простая фильтрация, для объектов нужно проверять соответствие элемента коллекции значениям по тем же ключам, что и в переданном объекте.\n\n```javascript\nconst cars = [\n { brand: 'bmw', model: 'm5', year: 2014 },\n { brand: 'bmw', model: 'm4', year: 2013 },\n { brand: 'kia', model: 'sorento', year: 2014 },\n { brand: 'kia', model: 'rio', year: 2010 },\n { brand: 'kia', model: 'sportage', year: 2012 },\n]\nconst coll = new Enumerable(cars)\n\nconst result = coll\n .where(car => car.brand === 'kia')\n .where(car => car.year > 2011)\n\nresult.toArray()\n// [\n// { brand: 'kia', model: 'sorento', year: 2014 },\n// { brand: 'kia', model: 'sportage', year: 2012 },\n// ]\n\nconst result2 = coll.where({ brand: 'bmw' })\nresult2.toArray()\n// [\n// { brand: 'bmw', model: 'm5', year: 2014 },\n// { brand: 'bmw', model: 'm4', year: 2013 },\n// ]\n\nconst result3 = coll.where({ brand: 'kia', model: 'sorento' })\nresult3.toArray()\n// [\n// { brand: 'kia', model: 'sorento', year: 2014 },\n// ]\n\nconst result3 = coll.where({ brand: 'kia' }, { model: 'sorento' })\nresult3.toArray()\n// [\n// { brand: 'kia', model: 'sorento', year: 2014 },\n// ]\n\nconst result4 = coll.where({ brand: 'kia' }, car => car.year < 2013)\nresult4.toArray()\n// [\n// { brand: 'kia', model: 'rio', year: 2010 },\n// { brand: 'kia', model: 'sportage', year: 2012 },\n// ]\n```\n\n### Подсказки\n\n* Извлечь ключи из объекта можно функцией `Object.keys()`.\n* Проверка на функцию: `typeof <value> === 'function'`.\n* Метод [every()](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Array/every) проверяет, удовлетворяют ли все элементы массива условию, заданному в передаваемой функции. Подробнее в документации.\n","prepared_readme":"## Enumerable.js\n\nРеализуйте метод `where()`, основываясь на следующем интерфейсе:\n\nФункция может принимать любое количество параметров, каждый из которых может быть либо функцией, либо объектом. Для функций должна осуществляться простая фильтрация, для объектов нужно проверять соответствие элемента коллекции значениям по тем же ключам, что и в переданном объекте.\n\n```javascript\nconst cars = [\n { brand: 'bmw', model: 'm5', year: 2014 },\n { brand: 'bmw', model: 'm4', year: 2013 },\n { brand: 'kia', model: 'sorento', year: 2014 },\n { brand: 'kia', model: 'rio', year: 2010 },\n { brand: 'kia', model: 'sportage', year: 2012 },\n]\nconst coll = new Enumerable(cars)\n\nconst result = coll\n .where(car => car.brand === 'kia')\n .where(car => car.year > 2011)\n\nresult.toArray()\n// [\n// { brand: 'kia', model: 'sorento', year: 2014 },\n// { brand: 'kia', model: 'sportage', year: 2012 },\n// ]\n\nconst result2 = coll.where({ brand: 'bmw' })\nresult2.toArray()\n// [\n// { brand: 'bmw', model: 'm5', year: 2014 },\n// { brand: 'bmw', model: 'm4', year: 2013 },\n// ]\n\nconst result3 = coll.where({ brand: 'kia', model: 'sorento' })\nresult3.toArray()\n// [\n// { brand: 'kia', model: 'sorento', year: 2014 },\n// ]\n\nconst result3 = coll.where({ brand: 'kia' }, { model: 'sorento' })\nresult3.toArray()\n// [\n// { brand: 'kia', model: 'sorento', year: 2014 },\n// ]\n\nconst result4 = coll.where({ brand: 'kia' }, car => car.year < 2013)\nresult4.toArray()\n// [\n// { brand: 'kia', model: 'rio', year: 2010 },\n// { brand: 'kia', model: 'sportage', year: 2012 },\n// ]\n```\n\n### Подсказки\n\n* Извлечь ключи из объекта можно функцией `Object.keys()`.\n* Проверка на функцию: `typeof <value> === 'function'`.\n* Метод [every()](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Array/every) проверяет, удовлетворяют ли все элементы массива условию, заданному в передаваемой функции. Подробнее в документации.\n","has_solution":true,"entity_name":"Операция rest"},"units":[{"id":1425,"name":"theory","url":"/courses/js-collections/lessons/rest_operator/theory_unit"},{"id":1427,"name":"quiz","url":"/courses/js-collections/lessons/rest_operator/quiz_unit"},{"id":1426,"name":"exercise","url":"/courses/js-collections/lessons/rest_operator/exercise_unit"}],"links":[{"id":423172,"name":"Представление последовательностей","url":"https://ru.hexlet.io/courses/sequences/lessons/list/theory_unit"}],"ordered_units":[{"id":1425,"name":"theory","url":"/courses/js-collections/lessons/rest_operator/theory_unit"},{"id":1427,"name":"quiz","url":"/courses/js-collections/lessons/rest_operator/quiz_unit"},{"id":1426,"name":"exercise","url":"/courses/js-collections/lessons/rest_operator/exercise_unit"}],"id":715,"slug":"rest_operator","state":"approved","name":"Операция rest","course_order":900,"goal":"Рассматриваем интересную особенность, которая позволяет передавать разное количество параметров в функцию","self_study":null,"theory_video_provider":"vimeo","theory_video_uid":"174202653","theory":"В этом уроке мы познакомимся с фичей, которую представляют нам динамические языки. Она называется rest operator или операция rest.\n\n## Разоблачение списков\n\nВспомним пример со списками. В курсе Последовательности мы использовали специальный конструктор `l`, который принимает на вход любое количество параметров:\n\n<!-- TODO: тут идет отсылка к другому курсу \"JS: Последовательности\", без него будет не понятно о чем речь. Нужно либо менять пример, либо добавить в интро зависимость от этого курса -->\n\n```javascript\nconst numbers = l(1, 10, 23, 234)\n\nexport const l = (...elements) =>\n // elements [1, 10, 23, 234]\n elements.reverse().reduce((acc, item) => cons(item, acc), null)\n```\n\nКоличество параметров динамическое. Мы можем не передать ни одного, и тогда у нас получится пустой список. А можем передать их сколько угодно, и тогда они превращаются в один список.\n\nЕсли мы посмотрим определение этой функции, то увидим внутри новую синтаксическую конструкцию. Она выглядит как три точки, и после нее идет идентификатор. В данном случае это элемент. А три точки — это и есть rest operator.\n\nOperator переводится как операция, а не оператор. Это разные вещи.\n\nПри использовании этой операции все элементы помещаются в один массив. В комментарии `// elements [1, 10, 23, 234]` видно его содержимое для этого списка. И после этого мы работаем с ним как с обычным массивом. В нашем примере мы вызываем `reverse()`, `reduce()` и постепенно добавляем элементы в `null` через `cons`. В итоге получаем список.\n\nВ этом примере много элементов, которые были бы непонятны на тот момент, когда мы знакомились со списками. Поэтому в тот момент мы не рассказывали о том, как они устроены внутри. Это было бы довольно сложно понять. Но теперь мы знаем это и можем читать и писать такой код.\n\n## Общая форма\n\nОперацию rest можно комбинировать и с позиционными аргументами:\n\n```javascript\nconst fn = (a, b, ...theArgs) => {\n console.log(a)\n console.log(b)\n console.log(theArgs)\n}\n\nfn ('first')\n// first\n// undefined\n// []\n```\n\nВ данном случае видно, что мы можем передавать первый и второй, третий параметры и так далее. И в конце можем использовать rest operator.\n\n**Rest** — это остаток. Он используется только в конце. Его нельзя использовать в середине или в начале. Поэтому если он есть в определении функции, то будет в самом конце этой функции. Причем перед ним может быть любое количество аргументов.\n\nЭта функция принимает на вход параметры, которые соберутся в один массив. Если мы попытаемся вызвать эту функцию с одним параметром, то первый параметр будет `first`. Второй — `undefined`, потому что он не был передан.\n\nВ случае с rest ситуация другая. `theArgs` будет не `undefined`, а пустой массив. И это правильно, так как нам не придется делать внутри проверки на `undefined`. То есть если мы ничего не передали, массив будет пустой, что обычно является желаемым поведением. И дальше уже можно строить работу на основе этого подхода.\n\n## Массив\n\nВ стандартной библиотеке JavaScript операция rest периодически встречается. Один из самых популярных примеров — добавление элементов в массив. Функция `push` у массива работает так:\n\n```javascript\nconst arr = []\narr.push()\narr.push(1)\narr.push(100, 23, 5)\narr.push(3, 100)\n\nconsole.log(arr)\n// [ 1, 100, 23, 5, 3, 100 ]\n```\n\nЗдесь мы вызываем `push` без аргументов, и ничего не происходит. Также можем передать один, два и более аргументов. В итоге массив наполнится и будет выглядеть так:\n\n```javascript\nconsole.log(arr)\n// [ 1, 100, 23, 5, 3, 100 ]\n```\n\n## Выводы\n\nВ этом уроке мы познакомились с фичей, которая представляет нам динамические языки. Она называется rest operator или операция rest. Operator переводится как операция. При ее использовании все элементы помещаются в один массив rest — это остаток. Он используется только в конце. Его нельзя использовать в середине или в начале. Поэтому если он есть в определении функции, то будет в самом конце этой функции. Причем перед ним может быть любое количество аргументов.\n"},"lessonMember":null,"courseMember":null,"course":{"start_lesson":{"exercise":null,"units":[{"id":1404,"name":"theory","url":"/courses/js-collections/lessons/intro/theory_unit"}],"links":[],"ordered_units":[{"id":1404,"name":"theory","url":"/courses/js-collections/lessons/intro/theory_unit"}],"id":707,"slug":"intro","state":"approved","name":"Введение","course_order":100,"goal":"Знакомимся с целями курса и обсуждаем проект, над которым мы будем работать","self_study":null,"theory_video_provider":"vimeo","theory_video_uid":"174202449","theory":"В предыдущих курсах мы уже научились работать с составными данными и поняли, зачем они нужны. Также мы изучили концептуальные способы работы, которые не зависят от конкретного языка программирования.\n\nВ этом курсе мы разберем конкретные приемы, которые используются для работы с коллекциями в языке JavaScript. При этом они будут подходить и ко многим другим языкам.\n\n## Какие темы будем изучать\n\nСписки есть везде и их бывает много. Они окружают нас повсеместно. Например, в Хекслете есть списки:\n\n* Пользователей\n* Курсов\n* Уроков\n* Топиков\n* Комментариев\n\nЕще есть не связанные с конкретными вещами списки, которые вводятся на сайте. Они существуют только внутри кода.\n\nВ этом курсе мы изучим несколько новых типов данных: массивы, ассоциативные массивы и множества.\n\nТакже мы познакомимся со следующими темами:\n\n* **Передача параметров по ссылке и по значению** — более сложный механизм, чем мы изучали до этого\n* **Функции высшего порядка** — встроены в JavaScript и являются каноническим способом работы с коллекциями\n* **Spread- и rest-операции** — распространены в других языках программирования и позволяют сократить шаблонный код\n* **Destructing assignment** — деструктуризация. Техника, которая используется в функциональных программированиях и языках. Она часто соприкасается с другой техникой, которая называется pattern matching\n\nТакже в этом курсе мы познакомимся с новыми техниками программирования, которые не относятся напрямую к работе с коллекциями. Это будет связано с проектом, который мы будем делать.\n\nМы поговорим о техниках:\n\n* **Lazy Evaluation** — ленивые вычисления\n* **Memoization** — мемоизация\n* **Fluent interface** — текучий интерфейс\n\nЕще мы познакомимся с понятием **DSL — Domain-specific language**. Это специализированный язык для конкретной области применения. Здесь речь не о языке программирования, хотя это тоже возможно, но с некоторыми ограничениями.\n\nDSL делится на два типа:\n\n* **Внешний**. Сюда входят языки запросов SQL и XPath, языки разметки HTML и Markdown, регулярные выражения. Они не пишутся на целевом языке, а формируются как текст, который разбирается специальными инструментами\n* **Внутренний**. Сюда входит методика создания внутренних DSL — Fluent Interface. Внутренний DSL написан на целевом языке — на котором мы программируем. Этот DSL обычно является библиотекой. Ее API выглядит как естественный язык, при этом детали реализации спрятаны\n\nDSL — важный механизм, который позволяет создавать специализированные языки. Они уменьшают вероятность появления ошибок и позволяют эффективно и быстро выражать и формировать понятия для определенной предметной области.\n\n## С каким проектом будем работать\n\nВ этом курсе мы будем делать проект, который называется Linq. Это библиотека, которая пришла из мира .NET — из языка C-sharp. Она позволяет описывать, как мы хотим обработать коллекцию и выдавать результат.\n\nСразу рассмотрим пример:\n\n```javascript\nimport HexletLinq from 'hexlet-linq';\n\nconst cars = [\n { brand: 'bmw', model: 'm5', year: 2014 },\n { brand: 'bmw', model: 'm4', year: 2013 },\n { brand: 'kia' model: 'sorento', year: 2014},\n { brand: 'kia', model: 'rio', year: 2010 },\n { brand: 'kia', model: 'sportage', year: 2012 },\n];\nconst coll = HexletLinq.from(cars);\n```\n\nЗдесь мы формируем некоторую структуру — список машин. Каждая машина представлена некоторым объектом с определенным набором данных: бренд, модель и год выпуска.\n\nПосле этого с помощью нашей библиотеки мы формируем эту коллекцию через `HexletLinq.from(cars)` — здесь происходит оборачивание или враппинг массива.\n\nУ этой коллекции есть большое количество методов, которые позволяют ее обрабатывать.\n\nНапример, мы хотим получить все модели машин, отсортированных в обратном порядке по году и принадлежащие бренду Kia:\n\n```javascript\nconst result = coll.orderBy(car => car.year, 'desc')\n .where(car => car.brand === 'kia')\n .select(car => car.model).toArray()\n\n// [ 'sorento', 'sportage', 'rio' ]\n```\n\nЧтобы выполнить эту задачу, мы пишем код так, что он читается почти как английский язык. Мы говорим, что нужно отсортировать (order by) по году выпуска (year) в обратном порядке (desc). При этом нам нужно выбрать из этих машин только те, у которых бренд Kia (where brand kia).\n\nРезультат должен представлять не коллекцию машин, а коллекцию моделей. Поэтому достаем из машин их модели (select model).\n\nДальше у нас есть специальный метод `toArray`, который преобразует список к обычному массиву, и на выходе получаем `[ 'sorento', 'sportage', 'rio' ]`. Массив содержит все модели бренда Kia, которые отсортированы по году в обратном порядке.\n\n## Почему этот курс\n\nКакие преимущества есть при изучении этого курса:\n\n* Будем писать настоящий канонический JS-код с помощью функции высших порядков. Это код, который в реальности пишут в продакшене\n* Будем обучаться через рефакторинг, а код будет эволюционировать. Значит, проект будет становиться лучше — меняться по урокам\n* Будем разрабатывать проект через тесты\n* Нужно будет думать и включаться в каждое упражнение, которое мы предоставляем\n"},"id":124,"slug":"js-collections","challenges_count":11,"name":"JS: Коллекции","allow_indexing":true,"state":"approved","course_state":"finished","pricing_type":"paid","description":"На этом курсе вы изучите конкретные приемы в работе с коллекциями в языке JavaScript. Вы узнаете больше о массивах, ассоциативных массивах и множествах. В итоге вы научитесь представлять данные в виде множеств с помощью Set, использовать Map для создания словарей, создавать ленивые коллекции для уменьшения количества проходов и мемоизировать вызовы функций для оптимизации производительности. Работа с коллекциями в JavaScript пригодится, если вы решите оптимизировать производительность своего кода. Знания из этого курса помогут программистам ускорить и упростить работу с данными.","kind":"additional","updated_at":"2026-01-20T11:40:19.676Z","language":"javascript","duration_cache":48240,"skills":["Представлять данные в виде множеств с помощью Set","Использовать Map для создания словарей","Создавать ленивые коллекции для уменьшения количества проходов","Мемоизировать вызовы функций для оптимизации производительности"],"keywords":["Set","Map","текучий интерфейс","ленивые коллекции","мемоизация"],"lessons_count":11,"cover":"https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6NjM4OSwicHVyIjoiYmxvYl9pZCJ9fQ==--d301339bc142b8588582eee69ca033648170d5c2/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-collections/lessons/rest_operator/theory_unit","version":"0b0c6d4ebbd40fd58630a0dd89cc25544ccdf24e","encryptHistory":false,"clearHistory":false}"><style data-mantine-styles="true">:root, :host{--mantine-font-family: Arial, sans-serif;--mantine-font-family-headings: Arial, sans-serif;--mantine-heading-font-weight: normal;--mantine-radius-default: 0rem;--mantine-primary-color-filled: var(--mantine-color-indigo-filled);--mantine-primary-color-filled-hover: var(--mantine-color-indigo-filled-hover);--mantine-primary-color-light: var(--mantine-color-indigo-light);--mantine-primary-color-light-hover: var(--mantine-color-indigo-light-hover);--mantine-primary-color-light-color: var(--mantine-color-indigo-light-color);--mantine-spacing-xxl: calc(4rem * var(--mantine-scale));--mantine-font-size-xs: 12px;--mantine-font-size-sm: 14px;--mantine-font-size-md: 16px;--mantine-font-size-lg: clamp(16.0000px, calc(15.2727px + 0.2273vw), 18.0000px);--mantine-font-size-xl: clamp(16.0000px, calc(14.5455px + 0.4545vw), 20.0000px);--mantine-font-size-display-3: clamp(32.0000px, calc(26.1818px + 1.8182vw), 48.0000px);--mantine-font-size-display-2: clamp(36.0000px, calc(25.8182px + 3.1818vw), 64.0000px);--mantine-font-size-display-1: clamp(40.0000px, calc(25.4545px + 4.5455vw), 80.0000px);--mantine-font-size-h1: clamp(28.0000px, calc(23.6364px + 1.3636vw), 40.0000px);--mantine-font-size-h2: clamp(24.0000px, calc(21.0909px + 0.9091vw), 32.0000px);--mantine-font-size-h3: clamp(20.0000px, calc(17.0909px + 0.9091vw), 28.0000px);--mantine-font-size-h4: clamp(16.0000px, calc(13.0909px + 0.9091vw), 24.0000px);--mantine-font-size-h5: clamp(16.0000px, calc(14.5455px + 0.4545vw), 20.0000px);--mantine-font-size-h6: 1rem;--mantine-primary-color-0: var(--mantine-color-indigo-0);--mantine-primary-color-1: var(--mantine-color-indigo-1);--mantine-primary-color-2: var(--mantine-color-indigo-2);--mantine-primary-color-3: var(--mantine-color-indigo-3);--mantine-primary-color-4: var(--mantine-color-indigo-4);--mantine-primary-color-5: var(--mantine-color-indigo-5);--mantine-primary-color-6: var(--mantine-color-indigo-6);--mantine-primary-color-7: var(--mantine-color-indigo-7);--mantine-primary-color-8: var(--mantine-color-indigo-8);--mantine-primary-color-9: var(--mantine-color-indigo-9);--mantine-color-red-0: #ffeaea;--mantine-color-red-1: #fed4d4;--mantine-color-red-2: #f4a7a8;--mantine-color-red-3: #ec7878;--mantine-color-red-4: #e55050;--mantine-color-red-5: #e03131;--mantine-color-red-6: #e02829;--mantine-color-red-7: #c71a1c;--mantine-color-red-8: #b21218;--mantine-color-red-9: #9c0411;--mantine-color-violet-0: #fce9ff;--mantine-color-violet-1: #f1cfff;--mantine-color-violet-2: #e09bff;--mantine-color-violet-3: #d16fff;--mantine-color-violet-4: #be37fe;--mantine-color-violet-5: #b51afe;--mantine-color-violet-6: #b009ff;--mantine-color-violet-7: #9b00e4;--mantine-color-violet-8: #8a00cc;--mantine-color-violet-9: #7800b3;--mantine-color-indigo-0: #edecff;--mantine-color-indigo-1: #d6d5fe;--mantine-color-indigo-2: #aaa9f4;--mantine-color-indigo-3: #7b79eb;--mantine-color-indigo-4: #5451e4;--mantine-color-indigo-5: #3b37e0;--mantine-color-indigo-6: #2d2adf;--mantine-color-indigo-7: #1f1ec7;--mantine-color-indigo-8: #1819b2;--mantine-color-indigo-9: #0c149e;--mantine-color-cyan-0: #dffdff;--mantine-color-cyan-1: #caf5ff;--mantine-color-cyan-2: #99e8ff;--mantine-color-cyan-3: #64daff;--mantine-color-cyan-4: #3ccffe;--mantine-color-cyan-5: #24c8fe;--mantine-color-cyan-6: #00c2ff;--mantine-color-cyan-7: #00ade4;--mantine-color-cyan-8: #009acd;--mantine-color-cyan-9: #0085b5;--mantine-color-green-0: #e9fdec;--mantine-color-green-1: #d7f6dc;--mantine-color-green-2: #b0eab9;--mantine-color-green-3: #86df94;--mantine-color-green-4: #62d574;--mantine-color-green-5: #4ccf5f;--mantine-color-green-6: #3fcc54;--mantine-color-green-7: #2fb344;--mantine-color-green-8: #25a03b;--mantine-color-green-9: #138a2e;--mantine-color-yellow-0: #fff7e2;--mantine-color-yellow-1: #ffeecd;--mantine-color-yellow-2: #ffdc9c;--mantine-color-yellow-3: #ffc966;--mantine-color-yellow-4: #feb93a;--mantine-color-yellow-5: #feae1e;--mantine-color-yellow-6: #ffa90f;--mantine-color-yellow-8: #ca8200;--mantine-color-yellow-9: #af7000;--mantine-h1-font-size: clamp(28.0000px, calc(23.6364px + 1.3636vw), 40.0000px);--mantine-h1-font-weight: normal;--mantine-h2-font-size: clamp(24.0000px, calc(21.0909px + 0.9091vw), 32.0000px);--mantine-h2-font-weight: normal;--mantine-h3-font-size: clamp(20.0000px, calc(17.0909px + 0.9091vw), 28.0000px);--mantine-h3-font-weight: normal;--mantine-h4-font-size: clamp(16.0000px, calc(13.0909px + 0.9091vw), 24.0000px);--mantine-h4-font-weight: normal;--mantine-h5-font-size: clamp(16.0000px, calc(14.5455px + 0.4545vw), 20.0000px);--mantine-h5-font-weight: normal;--mantine-h6-font-size: 1rem;--mantine-h6-font-weight: normal;}
:root[data-mantine-color-scheme="dark"], :host([data-mantine-color-scheme="dark"]){--mantine-color-anchor: var(--mantine-color-text);--mantine-color-dimmed: #495057;--mantine-color-dark-filled: var(--mantine-color-dark-5);--mantine-color-dark-filled-hover: var(--mantine-color-dark-6);--mantine-color-dark-light: rgba(105, 105, 105, 0.15);--mantine-color-dark-light-hover: rgba(105, 105, 105, 0.2);--mantine-color-dark-light-color: var(--mantine-color-dark-0);--mantine-color-dark-outline: var(--mantine-color-dark-1);--mantine-color-dark-outline-hover: rgba(184, 184, 184, 0.05);--mantine-color-gray-filled: var(--mantine-color-gray-5);--mantine-color-gray-filled-hover: var(--mantine-color-gray-6);--mantine-color-gray-light: rgba(222, 226, 230, 0.15);--mantine-color-gray-light-hover: rgba(222, 226, 230, 0.2);--mantine-color-gray-light-color: var(--mantine-color-gray-0);--mantine-color-gray-outline: var(--mantine-color-gray-1);--mantine-color-gray-outline-hover: rgba(241, 243, 245, 0.05);--mantine-color-red-filled: var(--mantine-color-red-5);--mantine-color-red-filled-hover: var(--mantine-color-red-6);--mantine-color-red-light: rgba(236, 120, 120, 0.15);--mantine-color-red-light-hover: rgba(236, 120, 120, 0.2);--mantine-color-red-light-color: var(--mantine-color-red-0);--mantine-color-red-outline: var(--mantine-color-red-1);--mantine-color-red-outline-hover: rgba(254, 212, 212, 0.05);--mantine-color-pink-filled: var(--mantine-color-pink-5);--mantine-color-pink-filled-hover: var(--mantine-color-pink-6);--mantine-color-pink-light: rgba(250, 162, 193, 0.15);--mantine-color-pink-light-hover: rgba(250, 162, 193, 0.2);--mantine-color-pink-light-color: var(--mantine-color-pink-0);--mantine-color-pink-outline: var(--mantine-color-pink-1);--mantine-color-pink-outline-hover: rgba(255, 222, 235, 0.05);--mantine-color-grape-filled: var(--mantine-color-grape-5);--mantine-color-grape-filled-hover: var(--mantine-color-grape-6);--mantine-color-grape-light: rgba(229, 153, 247, 0.15);--mantine-color-grape-light-hover: rgba(229, 153, 247, 0.2);--mantine-color-grape-light-color: var(--mantine-color-grape-0);--mantine-color-grape-outline: var(--mantine-color-grape-1);--mantine-color-grape-outline-hover: rgba(243, 217, 250, 0.05);--mantine-color-violet-filled: var(--mantine-color-violet-5);--mantine-color-violet-filled-hover: var(--mantine-color-violet-6);--mantine-color-violet-light: rgba(209, 111, 255, 0.15);--mantine-color-violet-light-hover: rgba(209, 111, 255, 0.2);--mantine-color-violet-light-color: var(--mantine-color-violet-0);--mantine-color-violet-outline: var(--mantine-color-violet-1);--mantine-color-violet-outline-hover: rgba(241, 207, 255, 0.05);--mantine-color-indigo-filled: var(--mantine-color-indigo-5);--mantine-color-indigo-filled-hover: var(--mantine-color-indigo-6);--mantine-color-indigo-light: rgba(123, 121, 235, 0.15);--mantine-color-indigo-light-hover: rgba(123, 121, 235, 0.2);--mantine-color-indigo-light-color: var(--mantine-color-indigo-0);--mantine-color-indigo-outline: var(--mantine-color-indigo-1);--mantine-color-indigo-outline-hover: rgba(214, 213, 254, 0.05);--mantine-color-blue-filled: var(--mantine-color-blue-5);--mantine-color-blue-filled-hover: var(--mantine-color-blue-6);--mantine-color-blue-light: rgba(116, 192, 252, 0.15);--mantine-color-blue-light-hover: rgba(116, 192, 252, 0.2);--mantine-color-blue-light-color: var(--mantine-color-blue-0);--mantine-color-blue-outline: var(--mantine-color-blue-1);--mantine-color-blue-outline-hover: rgba(208, 235, 255, 0.05);--mantine-color-cyan-filled: var(--mantine-color-cyan-5);--mantine-color-cyan-filled-hover: var(--mantine-color-cyan-6);--mantine-color-cyan-light: rgba(100, 218, 255, 0.15);--mantine-color-cyan-light-hover: rgba(100, 218, 255, 0.2);--mantine-color-cyan-light-color: var(--mantine-color-cyan-0);--mantine-color-cyan-outline: var(--mantine-color-cyan-1);--mantine-color-cyan-outline-hover: rgba(202, 245, 255, 0.05);--mantine-color-teal-filled: var(--mantine-color-teal-5);--mantine-color-teal-filled-hover: var(--mantine-color-teal-6);--mantine-color-teal-light: rgba(99, 230, 190, 0.15);--mantine-color-teal-light-hover: rgba(99, 230, 190, 0.2);--mantine-color-teal-light-color: var(--mantine-color-teal-0);--mantine-color-teal-outline: var(--mantine-color-teal-1);--mantine-color-teal-outline-hover: rgba(195, 250, 232, 0.05);--mantine-color-green-filled: var(--mantine-color-green-5);--mantine-color-green-filled-hover: var(--mantine-color-green-6);--mantine-color-green-light: rgba(134, 223, 148, 0.15);--mantine-color-green-light-hover: rgba(134, 223, 148, 0.2);--mantine-color-green-light-color: var(--mantine-color-green-0);--mantine-color-green-outline: var(--mantine-color-green-1);--mantine-color-green-outline-hover: rgba(215, 246, 220, 0.05);--mantine-color-lime-filled: var(--mantine-color-lime-5);--mantine-color-lime-filled-hover: var(--mantine-color-lime-6);--mantine-color-lime-light: rgba(192, 235, 117, 0.15);--mantine-color-lime-light-hover: rgba(192, 235, 117, 0.2);--mantine-color-lime-light-color: var(--mantine-color-lime-0);--mantine-color-lime-outline: var(--mantine-color-lime-1);--mantine-color-lime-outline-hover: rgba(233, 250, 200, 0.05);--mantine-color-yellow-filled: var(--mantine-color-yellow-5);--mantine-color-yellow-filled-hover: var(--mantine-color-yellow-6);--mantine-color-yellow-light: rgba(255, 201, 102, 0.15);--mantine-color-yellow-light-hover: rgba(255, 201, 102, 0.2);--mantine-color-yellow-light-color: var(--mantine-color-yellow-0);--mantine-color-yellow-outline: var(--mantine-color-yellow-1);--mantine-color-yellow-outline-hover: rgba(255, 238, 205, 0.05);--mantine-color-orange-filled: var(--mantine-color-orange-5);--mantine-color-orange-filled-hover: var(--mantine-color-orange-6);--mantine-color-orange-light: rgba(255, 192, 120, 0.15);--mantine-color-orange-light-hover: rgba(255, 192, 120, 0.2);--mantine-color-orange-light-color: var(--mantine-color-orange-0);--mantine-color-orange-outline: var(--mantine-color-orange-1);--mantine-color-orange-outline-hover: rgba(255, 232, 204, 0.05);--app-cta-gradient: linear-gradient(90deg, var(--mantine-color-blue-9) 0%, var(--mantine-color-cyan-7) 100%);--app-color-surface: #2e2e2e;}
:root[data-mantine-color-scheme="light"], :host([data-mantine-color-scheme="light"]){--mantine-color-anchor: var(--mantine-color-text);--mantine-color-dimmed: #495057;--mantine-color-red-light: rgba(224, 40, 41, 0.1);--mantine-color-red-light-hover: rgba(224, 40, 41, 0.12);--mantine-color-red-outline-hover: rgba(224, 40, 41, 0.05);--mantine-color-violet-light: rgba(176, 9, 255, 0.1);--mantine-color-violet-light-hover: rgba(176, 9, 255, 0.12);--mantine-color-violet-outline-hover: rgba(176, 9, 255, 0.05);--mantine-color-indigo-light: rgba(45, 42, 223, 0.1);--mantine-color-indigo-light-hover: rgba(45, 42, 223, 0.12);--mantine-color-indigo-outline-hover: rgba(45, 42, 223, 0.05);--mantine-color-cyan-light: rgba(0, 194, 255, 0.1);--mantine-color-cyan-light-hover: rgba(0, 194, 255, 0.12);--mantine-color-cyan-outline-hover: rgba(0, 194, 255, 0.05);--mantine-color-green-light: rgba(63, 204, 84, 0.1);--mantine-color-green-light-hover: rgba(63, 204, 84, 0.12);--mantine-color-green-outline-hover: rgba(63, 204, 84, 0.05);--mantine-color-yellow-light: rgba(255, 169, 15, 0.1);--mantine-color-yellow-light-hover: rgba(255, 169, 15, 0.12);--mantine-color-yellow-outline-hover: rgba(255, 169, 15, 0.05);--app-color-surface: #f1f3f5;--app-cta-gradient: linear-gradient(90deg, var(--mantine-color-blue-filled) 0%, var(--mantine-color-cyan-5) 100%);}</style><style data-mantine-styles="classes">@media (max-width: 35.99375em) {.mantine-visible-from-xs {display: none !important;}}@media (min-width: 36em) {.mantine-hidden-from-xs {display: none !important;}}@media (max-width: 47.99375em) {.mantine-visible-from-sm {display: none !important;}}@media (min-width: 48em) {.mantine-hidden-from-sm {display: none !important;}}@media (max-width: 61.99375em) {.mantine-visible-from-md {display: none !important;}}@media (min-width: 62em) {.mantine-hidden-from-md {display: none !important;}}@media (max-width: 74.99375em) {.mantine-visible-from-lg {display: none !important;}}@media (min-width: 75em) {.mantine-hidden-from-lg {display: none !important;}}@media (max-width: 87.99375em) {.mantine-visible-from-xl {display: none !important;}}@media (min-width: 88em) {.mantine-hidden-from-xl {display: none !important;}}</style><div style="position:absolute;top:0rem" class=""></div><div style="max-width:var(--container-size-xl);height:100%;min-height:0rem" class=""><style data-mantine-styles="inline">.__m__-_R_5ub_{--grid-gutter:0rem;}</style><div style="height:100%;min-height:0rem" class="m_410352e9 mantine-Grid-root __m__-_R_5ub_"><div class="m_dee7bd2f mantine-Grid-inner" style="height:100%"><style data-mantine-styles="inline">.__m__-_R_rdub_{--col-flex-grow:auto;--col-flex-basis:91.66666666666667%;--col-max-width:91.66666666666667%;}@media(min-width: 48em){.__m__-_R_rdub_{--col-flex-grow:auto;--col-flex-basis:83.33333333333334%;--col-max-width:83.33333333333334%;}}</style><div style="min-width:0rem;height:100%;min-height:0rem;display:flex" class="m_96bdd299 mantine-Grid-col __m__-_R_rdub_"><style data-mantine-styles="inline">.__m__-_R_6qrdub_{margin-top:0rem;padding-inline:var(--mantine-spacing-xs);width:100%;}@media(min-width: 48em){.__m__-_R_6qrdub_{margin-top:var(--mantine-spacing-xl);width:80%;}}@media(min-width: 62em){.__m__-_R_6qrdub_{padding-inline:var(--mantine-spacing-xl);}}</style><div style="margin-inline:auto;max-width:var(--mantine-breakpoint-xl)" class="__m__-_R_6qrdub_"><div style="color:var(--mantine-color-dimmed)" class="m_4451eb3a mantine-Center-root" data-inline="true"><div style="--ti-size:var(--ti-size-xs);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;margin-inline-end:calc(0.125rem * var(--mantine-scale));color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="xs"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-lock "><path d="M5 13a2 2 0 0 1 2 -2h10a2 2 0 0 1 2 2v6a2 2 0 0 1 -2 2h-10a2 2 0 0 1 -2 -2v-6"></path><path d="M11 16a1 1 0 1 0 2 0a1 1 0 0 0 -2 0"></path><path d="M8 11v-4a4 4 0 1 1 8 0v4"></path></svg></div><p style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">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">Теория: Операция rest</h1><script type="application/ld+json">{"@context":"https://schema.org","@type":"LearningResource","name":"Операция rest","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>В этом уроке мы познакомимся с фичей, которую представляют нам динамические языки. Она называется rest operator или операция rest.</p>
<h2 id="heading-2-1">Разоблачение списков</h2>
<p>Вспомним пример со списками. В курсе Последовательности мы использовали специальный конструктор <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">l</code>, который принимает на вход любое количество параметров:</p>
<!-- -->
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">const numbers = l(1, 10, 23, 234)
export const l = (...elements) =>
// elements [1, 10, 23, 234]
elements.reverse().reduce((acc, item) => cons(item, acc), 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>Количество параметров динамическое. Мы можем не передать ни одного, и тогда у нас получится пустой список. А можем передать их сколько угодно, и тогда они превращаются в один список.</p>
<p>Если мы посмотрим определение этой функции, то увидим внутри новую синтаксическую конструкцию. Она выглядит как три точки, и после нее идет идентификатор. В данном случае это элемент. А три точки — это и есть rest operator.</p>
<p>Operator переводится как операция, а не оператор. Это разные вещи.</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">// elements [1, 10, 23, 234]</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">reverse()</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">reduce()</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">null</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">cons</code>. В итоге получаем список.</p>
<p>В этом примере много элементов, которые были бы непонятны на тот момент, когда мы знакомились со списками. Поэтому в тот момент мы не рассказывали о том, как они устроены внутри. Это было бы довольно сложно понять. Но теперь мы знаем это и можем читать и писать такой код.</p>
<h2 id="heading-2-2">Общая форма</h2>
<p>Операцию rest можно комбинировать и с позиционными аргументами:</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 fn = (a, b, ...theArgs) => {
console.log(a)
console.log(b)
console.log(theArgs)
}
fn ('first')
// first
// undefined
// []</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>В данном случае видно, что мы можем передавать первый и второй, третий параметры и так далее. И в конце можем использовать rest operator.</p>
<p><strong>Rest</strong> — это остаток. Он используется только в конце. Его нельзя использовать в середине или в начале. Поэтому если он есть в определении функции, то будет в самом конце этой функции. Причем перед ним может быть любое количество аргументов.</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">first</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">undefined</code>, потому что он не был передан.</p>
<p>В случае с rest ситуация другая. <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">theArgs</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">undefined</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">undefined</code>. То есть если мы ничего не передали, массив будет пустой, что обычно является желаемым поведением. И дальше уже можно строить работу на основе этого подхода.</p>
<h2 id="heading-2-3">Массив</h2>
<p>В стандартной библиотеке JavaScript операция rest периодически встречается. Один из самых популярных примеров — добавление элементов в массив. Функция <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">push</code> у массива работает так:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">const arr = []
arr.push()
arr.push(1)
arr.push(100, 23, 5)
arr.push(3, 100)
console.log(arr)
// [ 1, 100, 23, 5, 3, 100 ]</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">push</code> без аргументов, и ничего не происходит. Также можем передать один, два и более аргументов. В итоге массив наполнится и будет выглядеть так:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">console.log(arr)
// [ 1, 100, 23, 5, 3, 100 ]</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>
<h2 id="heading-2-4">Выводы</h2>
<p>В этом уроке мы познакомились с фичей, которая представляет нам динамические языки. Она называется rest operator или операция rest. Operator переводится как операция. При ее использовании все элементы помещаются в один массив rest — это остаток. Он используется только в конце. Его нельзя использовать в середине или в начале. Поэтому если он есть в определении функции, то будет в самом конце этой функции. Причем перед ним может быть любое количество аргументов.</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-collections/lessons/rest_operator/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 / 11</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-collections/lessons/rest_operator/finish_unit?unit=theory" data-disabled="true" data-block="true" disabled=""><span class="m_80f1301b mantine-Button-inner"><span class="m_811560b9 mantine-Button-label">→</span></span></a><button style="--ai-size:var(--ai-size-sm);--ai-bg:transparent;--ai-hover:var(--mantine-color-indigo-light-hover);--ai-color:var(--mantine-color-indigo-light-color);--ai-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;padding-block:var(--mantine-spacing-lg);color:inherit;width:100%" class="mantine-focus-auto m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="subtle" data-size="sm" data-disabled="true" type="button" disabled=""><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-list-numbers "><path d="M11 6h9"></path><path d="M11 12h9"></path><path d="M12 18h8"></path><path d="M4 16a2 2 0 1 1 4 0c0 .591 -.5 1 -1 1.5l-3 2.5h4"></path><path d="M6 10v-6l-2 2"></path></svg></span></button><button style="--ai-size:var(--ai-size-sm);--ai-bg:transparent;--ai-hover:var(--mantine-color-indigo-light-hover);--ai-color:var(--mantine-color-indigo-light-color);--ai-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;padding-block:var(--mantine-spacing-lg);color:inherit;width:100%" class="mantine-focus-auto mantine-active m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="subtle" data-size="sm" type="button"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-message "><path d="M8 9h8"></path><path d="M8 13h6"></path><path d="M18 4a3 3 0 0 1 3 3v8a3 3 0 0 1 -3 3h-5l-5 3v-3h-2a3 3 0 0 1 -3 -3v-8a3 3 0 0 1 3 -3h12"></path></svg></span></button></div></div></div></div></div></div></div>
</main>
<footer class="bg-dark fw-light text-light px-3 py-5">
<div class="row small">
<div class="col-12 col-sm-6 col-md-3">
<div class="h5 mb-3">Хекслет</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/about">О нас</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/testimonials">Отзывы</a>
</li>
<li>
<span class="nav-link link-light py-1 ps-0 external-link" data-href="https://b2b.hexlet.io" role="button">Корпоративное обучение</span>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/blog">Блог</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/qna">Вопросы и ответы</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/glossary">Глоссарий</a>
</li>
<li>
<span class="nav-link link-light py-1 ps-0 external-link" data-href="https://help.hexlet.io" data-target="_blank" role="button">Справка</span>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" target="_blank" rel="noopener noreferrer" href="/map">Карта сайта</a>
</li>
</ul>
</div>
<div class="col-12 col-sm-6 col-md-3">
<div class="h5 fw-normal mb-3">Направления</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_devops">DevOps
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_data_analytics">Аналитика
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_backend_development">Бэкенд
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_programming">Программирование
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_testing">Тестирование
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_front_end_dev">Фронтенд
</a></li>
</ul>
</div>
<div class="col-12 col-sm-6 col-md-3">
<div class="h5">Профессии</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/devops-engineer-from-scratch">DevOps-инженер с нуля</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/go">Go-разработчик</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/java">Java-разработчик</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/python">Python-разработчик </a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/data-analytics">Аналитик данных</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/qa-engineer">Инженер по ручному тестированию</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/php">РНР-разработчик</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/frontend">Фронтенд-разработчик</a>
</li>
</ul>
</div>
<div class="col-12 col-sm-6 col-md-3">
<div class="h5">Навыки</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/python-django-developer">Django</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/docker">Docker</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/php-laravel-developer">Laravel</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/postman">Postman</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/js-react-developer">React</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/js-rest-api">REST API в Node.js</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/spring-boot">Spring Boot</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/typescript">Typescript</a>
</li>
</ul>
</div>
</div>
<hr>
<div class="row">
<div class="col-12 col-sm-4 col-md-2">
<div class="fs-4">
<ul class="list-unstyled d-flex">
<li class="me-3">
<a aria-label="Telegram" target="_blank" class="link-light" rel="noopener noreferrer nofollow" href="https://t.me/hexlet_ru"><span class="bi bi-telegram"></span>
</a></li>
<li>
<a aria-label="Youtube" target="_blank" class="link-light" rel="noopener noreferrer nofollow" href="https://www.youtube.com/user/HexletUniversity"><span class="bi bi-youtube"></span>
</a></li>
</ul>
</div>
<div class="mb-2 d-flex flex-column">
<a class="link-light text-decoration-none" rel="nofollow" href="mailto:support@hexlet.io">support@hexlet.io</a>
<a class="link-light text-decoration-none py-2" target="_blank" href="https://t.me/hexlet_help_bot">t.me/hexlet_help_bot</a>
</div>
<ul class="list-unstyled d-flex">
<li class="me-3">
<span class="link-light text-decoration-none opacity-50 x-font-size-18 external-link" rel="nofollow" data-href="https://hexlet.io/locale/switch?new_locale=en" data-target="_self" role="button"><span class="my-auto">EN</span>
</span></li>
<li class="me-3">
<span class="link-light text-decoration-none opacity-50 x-font-size-18 opacity-100 external-link" rel="nofollow" data-href="https://ru.hexlet.io/locale/switch?new_locale=ru" data-target="_self" role="button"><span class="my-auto">RU</span>
</span></li>
<li class="me-3">
<span class="link-light text-decoration-none opacity-50 x-font-size-18 external-link" rel="nofollow" data-href="https://kz.hexlet.io/locale/switch?new_locale=kz" data-target="_self" role="button"><span class="my-auto">KZ</span>
</span></li>
</ul>
</div>
<div class="col-12 col-sm-4 col-md-3">
<ul class="list-unstyled fs-4">
<li class="mb-3">
<a class="link-light text-decoration-none" href="tel:8%20800%20100%2022%2047">8 800 100 22 47</a>
<span class="d-block opacity-50 small">бесплатно по РФ</span>
</li>
<li>
<a class="link-light text-decoration-none" href="tel:%2B7%20495%20085%2021%2062">+7 495 085 21 62</a>
<span class="d-block opacity-50 small">бесплатно по Москве</span>
</li>
</ul>
</div>
<div class="col-12 col-sm-4 col-md-3">
<div class="small mb-3">Образовательные услуги оказываются на основании Л035-01298-77/01989008 от 14.03.2025</div>
<ul class="list-unstyled small">
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/legal">Правовая информация</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/offer">Оферта</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/license">Лицензия</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/contacts">Контакты</a>
</li>
</ul>
</div>
<div class="col-12 col-sm-12 col-md-4 small">
<div class="mb-2">
<div>ООО «<a href="/" class="text-decoration-none link-light">Хекслет Рус</a>»</div>
<div>108813 г. Москва, вн.тер.г. поселение Московский,</div>
<div>г. Московский, ул. Солнечная, д. 3А, стр. 1, помещ. 20Б/3</div>
<div>ОГРН 1217300010476</div>
<div>ИНН 7325174845</div>
</div>
<hr>
<div>АНО ДПО «<a href="/" class="text-decoration-none link-light">Учебный центр «Хекслет</a>»</div>
<div>119331 г. Москва, вн. тер. г. муниципальный округ</div>
<div>Ломоносовский, пр-кт Вернадского, д. 29</div>
<div>ОГРН 1247700712390</div>
<div>ИНН 7736364948</div>
</div>
</div>
</footer>
<div id="root-assistant-offcanvas"></div>
<script src="/vite/assets/assistant-CdBlNCiQ.js" crossorigin="anonymous" type="module"></script><link rel="modulepreload" href="/vite/assets/chunk-DsPFFUou.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/init-nkZBEvfU.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/ErrorFallbackBlock-naDSYSy9.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/MarkdownBlock-DbyKWoR_.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/gon-D3e4yh1x.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/mantine-CGMYrt2Y.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/shiki-V011pkdv.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/utils-DRqSHbQE.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/routes-CCH8ilKF.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/lib-XR8Qr8kR.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/dist-GCHh59xr.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Box-B5-OOzBf.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/notifications.store-C-3AFSMn.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/useIsomorphicEffect-HJ6VK0D3.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/lib-KSp6QbZ0.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/axios-BEvgo0ym.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/classnames-l6ipYlLR.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/dayjs.min-BkKovM-s.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/debounce-jMQ_Cf4f.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/i18next-BlSq9s7B.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/client-U9M77rxp.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-dom-DaLxUz_h.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/useTranslation-Bx1Cdrkz.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/compiler-runtime-6XxiPFnt.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/jsx-runtime-CwjcCKJi.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-CkL4ZRHB.js" as="script" crossorigin="anonymous">
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v67327c56f0bb4ef8b305cae61679db8f1769101564043" integrity="sha512-rdcWY47ByXd76cbCFzznIcEaCN71jqkWBBqlwhF1SY7KubdLKZiEGeP7AyieKZlGP9hbY/MhGrwXzJC/HulNyg==" data-cf-beacon='{"version":"2024.11.0","token":"d11015b65d11429ea6b4a2ef37dd7e0b","server_timing":{"name":{"cfCacheStatus":true,"cfEdge":true,"cfExtPri":true,"cfL4":true,"cfOrigin":true,"cfSpeedBrain":true},"location_startswith":null}}' crossorigin="anonymous"></script>
</body>
</html>