[{"data":1,"prerenderedAt":1316},["ShallowReactive",2],{"$foUgttE5siRuH2uIxBLLAI8Rb3l_cDl8VQgEYsb_mUx0":3,"$fMMUdSFktwQFqMVGPrTtt3EC5yheBp7PzwIqznamFcMo":125,"$f1Prj1xEczHja_-L7FyIGgRHd5_cSWHo7r6AE5aheAik":128,"$fc0LoAJgqXDLbKKd2JS_NpM4SuzBK8EycUXINSg09CKU":454,"$fM3ea55k6lKMPOTM84llDB26VSQDVVbxiQuSBFQw9P_c":457,"$fI5fDmvm-5tr9wcH0eHaKZa1j3y_FQIQaHHPqbZxAHJE":701,"mdc-hi9q3e-key":721,"mdc--gs7tsi-key":733,"mdc--30u2mb-key":741,"mdc-caornl-key":749,"mdc--4ak6ou-key":784,"mdc--db5ovk-key":792,"mdc--7otkjd-key":800,"mdc-eebqye-key":808,"mdc--y361xn-key":823,"mdc-4qd7wh-key":832,"mdc--i8fc6g-key":861,"mdc-uyg7wb-key":869,"mdc--l8uzeo-key":897,"mdc-meinv9-key":905,"mdc-y1rt9g-key":968,"mdc-n7cjjh-key":1021,"mdc-xz3kz7-key":1029,"mdc-7vh0i3-key":1060,"mdc--6vte68-key":1090,"mdc--5lx8z8-key":1148,"mdc--h3a4v3-key":1156,"mdc--8sgmd7-key":1308},{"content":4,"quizQuestionContent":95,"type":114,"pageMeta":115},[5,9,13,16,20,23,27,31,34,37,40,43,46,49,53,56,60,63,67,70,74,77,80,83,86,89,92],{"id":6,"value":7,"isTypeH1":8},"1895","Зачем нужен менеджер состояния в веб‑приложении",true,{"id":10,"value":11,"anchor":12,"isTypeH2":8},"4333","Теория: что такое состояние и почему возникают проблемы","theory-what-is-state-and-why-problems-appear",{"id":14,"value":15,"isTypeParagraph":8},"9960","Состояние (state) — это данные, которые меняются со временем и влияют на то, что видит пользователь: авторизация, профиль, корзина, фильтры, результаты запросов, настройки интерфейса.\n",{"id":17,"value":18,"anchor":19,"isTypeH3":8},"4334","Типичная эволюция сложности","typical-evolution-of-complexity",{"id":21,"value":22,"isTypeParagraph":8},"9961","1) Сначала состояние хранится локально в компонентах.  \n2) Затем одни и те же данные становятся нужны нескольким веткам интерфейса.  \n3) Начинается передача данных “сверху вниз” через несколько уровней компонентов (prop drilling).  \n4) Появляется риск рассинхронизации: разные части интерфейса обновляют похожие данные по-разному и в разное время.\n",{"id":24,"description":25,"titleAlert":26,"isTypeAlertInfo":8},"624","Менеджер состояния не является обязательной частью каждого проекта: в небольших приложениях нередко достаточно локального состояния компонентов и/или React Context, а отдельная библиотека чаще нужна при росте масштаба и сложности.",null,{"id":28,"value":29,"anchor":30,"isTypeH3":8},"4335","Что даёт менеджер состояния","what-a-state-manager-gives",{"id":32,"value":33,"isTypeParagraph":8},"9962","- Единый источник истины для общих данных (часто это единое хранилище, “store”).  \n- Явные способы изменения состояния: через события/действия и правила обновления (например, редьюсеры).  \n- Реактивные подписки: при изменении данных связанные части интерфейса обновляются автоматически.  \n- Упрощение диагностики: становится проще понять, что произошло (событие/действие) и по какому правилу изменились данные.",{"id":35,"description":36,"titleAlert":26,"isTypeAlertWarning":8},"682","Добавление менеджера состояния увеличивает “архитектурную нагрузку”: требуется договориться о структуре состояния и о том, как именно оно меняется; в маленьком проекте это может замедлять разработку.",{"id":17,"value":38,"anchor":39,"isTypeH2":8},"Пример проблемы: prop drilling и рассинхронизация","example-prop-drilling-and-desynchronization",{"id":41,"value":42,"isTypeParagraph":8},"9963","Ниже показана упрощённая ситуация: значение `user` требуется и вверху, и глубоко внутри дерева, а также участвует в загрузке данных.\n\n```\n// Пример: данные прокидываются через несколько уровней,\n// хотя промежуточным компонентам они не нужны.\n\nfunction App() {\n  const [user, setUser] = React.useState(null);\n\n  React.useEffect(() => {\n    fetch(\"/api/me\")\n      .then((r) => r.json())\n      .then(setUser);\n  }, []);\n\n  return (\n    \u003CLayout user={user}>\n      \u003CPage user={user} />\n    \u003C/Layout>\n  );\n}\n\nfunction Layout({ user, children }) {\n  return (\n    \u003Cdiv>\n      \u003CHeader user={user} />\n      {children}\n    \u003C/div>\n  );\n}\n\nfunction Page({ user }) {\n  return \u003CProfileCard user={user} />;\n}\n\nfunction ProfileCard({ user }) {\n  if (!user) return \u003Cspan>Loading...\u003C/span>;\n  return \u003Cdiv>Hello, {user.name}\u003C/div>;\n}\n```\n\nПроблемы такого подхода в больших приложениях:\n- Сложно менять структуру дерева компонентов: приходится “протягивать” пропсы через новые уровни.\n- Трудно гарантировать единообразное обновление, если похожие данные начинают храниться в нескольких местах.\n- Сложно отлаживать, кто и когда изменил данные, если обновления распределены по множеству компонентов.\n\nСхематично:\n\n```\nБез менеджера:\nApp (state)\n  ├─ Layout (просто пересылает user)\n  │    └─ Header (читает user)\n  └─ Page (просто пересылает user)\n       └─ ProfileCard (читает user)\n\nС менеджером:\nGlobal Store (state)\n  ├─ Header (подписка на store)\n  └─ ProfileCard (подписка на store)\n  ```\n",{"id":28,"value":44,"anchor":45,"isTypeH2":8},"Как это делают разные менеджеры состояния","how-different-state-managers-do-it",{"id":47,"value":48,"isTypeParagraph":8},"9964","Ниже приведены минимальные примеры, чтобы увидеть общую идею: состояние выносится из компонентов, а компоненты подписываются на изменения.",{"id":50,"value":51,"anchor":52,"isTypeH3":8},"4336","Redux: store, action, reducer","redux-store-action-reducer",{"id":54,"value":55,"isTypeParagraph":8},"9965","Идея: состояние хранится в `store`, изменение инициируется через `dispatch(action)`, а новый state вычисляется функцией `reducer`.\n\n```\nimport { createStore } from \"redux\";\n\n// Action (описание “что произошло”)\nconst setUser = (user) => ({ type: \"user/set\", payload: user });\n\n// Reducer (правило “как меняется state”)\nfunction reducer(state = { user: null }, action) {\n  switch (action.type) {\n    case \"user/set\":\n      return { ...state, user: action.payload };\n    default:\n      return state;\n  }\n}\n\nexport const store = createStore(reducer);\n\n// Где-то в коде загрузки данных:\nfetch(\"/api/me\")\n  .then((r) => r.json())\n  .then((user) => store.dispatch(setUser(user)));\n\n// В UI (псевдокод): подписка на store и чтение store.getState()\n```\n\nКлючевая мысль: компонентам не требуется получать `user` через цепочку пропсов, потому что чтение идёт из общего хранилища.",{"id":57,"value":58,"anchor":59,"isTypeH3":8},"4337","MobX: реактивные значения и производные данные","mobx-reactive-values-and-derived-data",{"id":61,"value":62,"isTypeParagraph":8},"9966","Идея: есть “наблюдаемые” данные, а UI автоматически обновляется, если были использованы значения, которые изменились.\n\n```\nimport { makeAutoObservable } from \"mobx\";\nimport { observer } from \"mobx-react-lite\";\n\nclass UserStore {\n  user = null;\n\n  constructor() {\n    makeAutoObservable(this);\n  }\n\n  setUser(user) {\n    this.user = user;\n  }\n\n  get userName() {\n    return this.user ? this.user.name : \"Loading...\";\n  }\n}\n\nexport const userStore = new UserStore();\n\n// UI: компонент реагирует на изменения используемых полей\nexport const Header = observer(() => {\n  return \u003Cdiv>Hello, {userStore.userName}\u003C/div>;\n});\n```\n\nКлючевая мысль: производные значения (например, `userName`) удобно держать рядом с моделью и получать автоматически обновляемый UI.",{"id":64,"value":65,"anchor":66,"isTypeH3":8},"4338","Effector: stores + events, обновление через события","effector-stores-and-events",{"id":68,"value":69,"isTypeParagraph":8},"9967","Идея: изменения описываются как события, а `store` обновляется реактивно в ответ на эти события.\n\n```\nimport { createEvent, createStore } from \"effector\";\n\n// Событие: “что произошло”\nconst userLoaded = createEvent();\n\n// Store: “где хранятся данные”\nconst $user = createStore(null)\n  .on(userLoaded, (_, user) => user);\n\n// Где-то в коде загрузки:\nfetch(\"/api/me\")\n  .then((r) => r.json())\n  .then(userLoaded);\n\n// UI (псевдокод): подписка на $user через bindings для фреймворка\n```\n\nКлючевая мысль: состояние меняется не “напрямую”, а через поток событий и описанные правила реакции store.",{"id":71,"value":72,"anchor":73,"isTypeH3":8},"4339","Zustand: минимальное хранилище и хук-подписка","zustand-minimal-store-and-hook-subscription",{"id":75,"value":76,"isTypeParagraph":8},"9968","Идея: создаётся небольшое хранилище, чтение делается через хук с селектором, обновление — через функцию `set`.\n\n```\nimport { create } from \"zustand\";\n\nconst useUserStore = create((set) => ({\n  user: null,\n  setUser: (user) => set({ user }),\n}));\n\nfunction Header() {\n  const user = useUserStore((s) => s.user);\n  return \u003Cdiv>Hello, {user ? user.name : \"Loading...\"}\u003C/div>;\n}\n\n// Загрузка данных:\nfetch(\"/api/me\")\n  .then((r) => r.json())\n  .then((user) => useUserStore.getState().setUser(user));\n```\n\nКлючевая мысль: компонент получает данные напрямую из хранилища и обновляется, когда меняется выбранный “срез” состояния.",{"id":50,"value":78,"anchor":79,"isTypeH2":8},"Когда менеджер состояния действительно нужен","when-a-state-manager-is-really-needed",{"id":81,"value":82,"isTypeParagraph":8},"9969","Менеджер состояния обычно оправдан, когда:\n- Одни и те же данные используются во многих независимых компонентах (например, пользователь, права, корзина).\n- Есть сложные сценарии обновлений (несколько источников событий, асинхронные запросы, зависимые вычисления).\n- Нужны единые правила, чтобы понимать “кто изменил состояние и почему” (события/действия + правила обновления).\n\nЧасто можно обойтись без отдельной библиотеки, когда:\n- Состояние локальное и используется внутри одного компонента или небольшой ветки.\n- Поднятия состояния на уровень выше достаточно, и цепочки передачи не становятся длинными.\n- React Context + `useReducer` покрывают потребности без сложных потоков данных.",{"id":84,"description":85,"titleAlert":26,"isTypeAlertInfo":8},"625","Выбор конкретной библиотеки обычно определяется архитектурой: строгие правила и предсказуемые обновления, реактивные вычисления, минималистичный API — это разные приоритеты, и они по-разному реализуются в Redux/MobX/Effector/Zustand.",{"id":57,"value":87,"anchor":88,"isTypeH2":8},"Таблица: краткое сравнение подходов","table-quick-comparison-of-approaches",{"id":90,"value":91,"isTypeParagraph":8},"9970","| Библиотека | Основная идея | Как меняется состояние | Типичный плюс |\n|---|---|---|---|\n| Redux | Единое хранилище + явные действия и правила | `dispatch(action)` → `reducer` возвращает новый state | Предсказуемость и единый стиль изменений |\n| MobX | Реактивные данные и вычисления | Изменение наблюдаемых данных, UI реагирует автоматически | Меньше “связующего” кода вокруг derived-логики |\n| Effector | События и реактивные stores | Store обновляется через события и реакции | Явные потоки событий и хорошая композиция |\n| Zustand | Минимальное хранилище | `set(...)`, подписка через хук с селектором | Простота и малое количество абстракций |\n",{"id":93,"value":94,"isTypeParagraph":8},"9971","Итого: менеджер состояния нужен для согласованного хранения и обновления общих данных в приложении: он снижает риск рассинхронизации, упрощает отслеживание изменений и уменьшает необходимость передачи данных через длинные цепочки компонентов.",{"id":96,"options":97,"hint":111,"solution":112,"description":113},"1134",[98,102,105,108],{"id":99,"label":100,"isCorrect":101},"4668","Для повышения скорости загрузки страницы за счет сжатия передаваемых данных между клиентом и сервером.",false,{"id":103,"label":104,"isCorrect":8},"4669","Для централизованного управления состоянием приложения, что решает проблемы рассинхронизации данных, сложного отслеживания изменений и 'пропс-дриллинга' в больших приложениях.",{"id":106,"label":107,"isCorrect":101},"4670","Чтобы писать меньше JavaScript-кода в компонентах и полностью переложить логику отображения на CSS.",{"id":109,"label":110,"isCorrect":101},"4671","Для автоматической генерации HTML-разметки и стилей на основе описания состояния в JavaScript.","В тестах по теме state management почти всегда правильный вариант связан с тем, что библиотека хранит общее состояние и предоставляет понятные правила его изменения: это помогает бороться с рассинхронизацией, усложнением отслеживания изменений и необходимостью “протягивать” данные через множество компонентов.","**Правильный ответ: 2** - для централизованного управления состоянием приложения, что решает проблемы рассинхронизации данных, сложного отслеживания изменений и 'пропс-дриллинга' в больших приложениях.","Зачем нужен менеджер состояния (Redux, MobX, Effector, Zustand) в веб-приложении?","quizQuestion",{"title":116,"description":117,"ogTitle":7,"ogDescription":117,"ogImageUrl":118,"canonical":26,"ogLocale":119,"ogSiteName":120,"ogImageType":121,"ogImageWidth":122,"ogImageHeight":123,"ogType":124,"ogUrl":26},"Менеджеры состояния в веб-приложениях: проблемы и решения","Объяснение роли Redux/MobX/Effector/Zustand: зачем нужен общий state, какие проблемы решает и когда достаточно Context.","/og-image.png","ru_RU","goodwebjob.ru","image_jpeg","1200","630","article",{"siteName":126,"siteUrl":127},"GOOD WEB JOB!","https://goodwebjob.ru",{"slugs":129},[130,133,136,139,142,145,148,151,154,157,160,163,166,169,172,175,178,181,184,187,190,193,196,199,202,205,208,211,214,217,220,223,226,229,232,235,238,241,244,247,250,253,256,259,262,265,268,271,274,277,280,283,286,289,292,295,298,301,304,307,310,313,316,319,322,325,328,331,334,337,340,343,346,349,352,355,358,361,364,367,370,373,376,379,382,385,388,391,394,397,400,403,406,409,412,415,418,421,424,427,430,433,436,439,442,445,448,451],{"name":131,"value":132},"Теоретические задания","theoretical-tasks",{"name":134,"value":135},"Что вернёт этот код: typeof (function(){})()","what-this-code-will-return-typeof-function",{"name":137,"value":138},"С чего начать?","where-to-begin",{"name":140,"value":141},"Почему опасно писать прямо в прототипы базовых типов?","why-is-it-dangerous-to-write-directly-to-the-prototypes-of-basic-types",{"name":143,"value":144},"Backend","backend",{"name":146,"value":147},"Frontend","frontend",{"name":149,"value":150},"Какие логические значения в console.log будут получены?","prototype-what-logical-values-will-be-received-in-console-log",{"name":152,"value":153},"Нечётные числа должны отсортироваться по возрастанию, а чётные должны остаться на своих местах","odd-numbers-should-be-sorted-in-ascending-order-and-even-numbers-should-remain-in-their-original-positions",{"name":155,"value":156}," Найти в массиве неповторяющиеся числа","find-non-repeating-numbers-in-an-array",{"name":158,"value":159},"arr.push(0) повлияет на массив так же, как если бы мы выполнили...","arr-push-0-will-affect-the-array-in-the-same-way-as-if-we-performed",{"name":161,"value":162},"Дана строка: 'one.two.three.four.five'. Необходимо из строки сделать вложенный объект","the-string-one-two-three-four-five-is-given-it-is-necessary-to-make-a-nested-object-out-of-the-string",{"name":164,"value":165},"Реализовать функцию, похоже как в Jquery","implement-a-function-similar-to-jquery",{"name":167,"value":168},"Для каждого вложенного объекта нужно добавить свойство level, которое равняется числу - номер вложенности","for-each-nested-object-you-need-to-add-the-level-property-which-is-equal-to-a-number-the-nesting-number",{"name":170,"value":171},"Какое значение выведет консоль с object.property?","what-value-will-the-console-output-with-object-property",{"name":173,"value":174},"Что выведется в console.log([arr[0](), arr[0]()])?","what-will-be-displayed-in-console-log-arr-0-arr-0",{"name":176,"value":177},"Вернуть массив от 1 до n, где числа, кратные 3, заменены на 'fizz', кратные 5 - на 'buzz', а кратные и 3, и 5 одновременно - на 'fizzbuzz'","returns-an-array-from-1-to-n-replacing-numbers-that-are-multiples-of-3-with-fizz-numbers-that-are-multiples-of-5-with-buzz-and-numbers-that-are-multiples-of-both-3-and-5-with-fizzbuzz",{"name":179,"value":180},"Необходимо проверить, являются ли две строки анаграммами друг друга","checks-whether-two-strings-are-anagrams-of-each-other",{"name":182,"value":183},"Определить, является ли слово палиндромом","determines-whether-a-word-is-a-palindrome",{"name":185,"value":186},"Есть массив, в котором лежат объекты с датами, необходимо отсортировать даты по возрастанию","there-is-an-array-containing-objects-with-dates-that-need-to-be-sorted-by-date",{"name":188,"value":189},"Реализовать функцию, принимающую аргументы \"*\", \"1\", \"b\", \"1c\" и возвращающую строку \"1*b*1c\"","implement-a-function-that-accepts-arguments-1-b-1c-and-the-return-string-1-b-1c",{"name":191,"value":192},"Дано дерево (вложенный объект), надо найти сумму всех вершин","given-a-tree-nested-object-it-is-necessary-to-find-the-sum-of-all-vertices",{"name":194,"value":195},"Для каждой ветви дерева записать номер вложенности данной ветви","for-each-branch-of-the-tree-write-down-the-nesting-number-of-this-branch",{"name":197,"value":198},"Есть слова в массиве, необходимо определить, состоят ли они из одних и тех же букв","there-are-words-in-the-array-it-is-necessary-to-determine-whether-they-consist-of-the-same-letters",{"name":200,"value":201},"Числа от 1 до 100 находятся в массиве, они хаотично перемешанные, но в нём не хватает одного числа из этой последовательности. Необходимо найти его","the-numbers-from-1-to-100-are-in-the-array-they-are-randomly-mixed-but-it-lacks-one-number-from-this-sequence-it-is-necessary-to-find-him",{"name":203,"value":204},"Есть строка, состоящая из разных скобок, необходимо проверить, закрыты ли все","there-is-a-string-consisting-of-different-brackets-it-is-necessary-to-check-whether-all-are-closed",{"name":206,"value":207},"Напишите функцию, который сделает из массива объект","write-a-function-that-will-make-an-object-out-of-an-array",{"name":209,"value":210},"Что выведет console.log в результате выполнения цикла while?","what-will-console-log-output-as-a-result-of-executing-the-while-loop",{"name":212,"value":213},"Есть функция и объект. Напишите все известные вам способы, чтобы вывести в консоли значение x из объекта, используя функцию","there-is-a-function-and-an-object-write-all-the-ways-you-know-to-output-the-value-of-x-from-an-object-in-the-console-using-the-function",{"name":215,"value":216},"Что выведет консоль в случае присвоения свойства массиву по строковому отрицательному индексу?","what-will-the-console-display-if-a-property-is-assigned-to-an-array-using-a-negative-string-index",{"name":218,"value":219},"Что выведет консоль в случае удаления элемента массива с помощью оператора delete?","what-will-the-console-output-if-an-array-element-is-deleted-using-the-delete-operator",{"name":221,"value":222},"Уникализация значений в массиве","unifying-values-in-an-array",{"name":224,"value":225},"«Расплющивание» массива","flattening-the-array",{"name":227,"value":228},"Что вернёт метод book.getUpperName()?","what-will-the-book-get-upper-name-method-return",{"name":230,"value":231},"Сжатие строк","string-compression",{"name":233,"value":234},"Что выведет консоль в случае присвоения свойства массиву по строковому положительному индексу?","what-will-the-console-display-if-a-property-is-assigned-to-an-array-using-a-positive-string-index",{"name":236,"value":237},"Что получится в результате передачи объекта как аргумента в функцию и выполнения кода?","what-will-happen-when-an-object-is-passed-as-an-argument-to-a-function-and-the-code-is-executed",{"name":239,"value":240},"Как браузер после ввода домена понимает, откуда брать сайт?","how-does-the-browser-know-where-to-get-the-website-after-entering-the-domain",{"name":242,"value":243},"Как домен попадает в DNS в таблицу соответствия: домен – ip","how-does-a-domain-get-into-the-dns-mapping-table-domain-ip",{"name":245,"value":246},"Как браузер решает, какое соединение ему открывать, TCP или UDP?","how-does-a-browser-decide-whether-to-open-a-tcp-or-udp-connection",{"name":248,"value":249},"Ключевые отличия TCP и UDP","key-differences-between-tcp-and-udp",{"name":251,"value":252},"\"TCP/IP\" - кем является TCP, а кем IP в данном случае?","tcp-ip-who-is-tcp-and-who-is-ip-in-this-case",{"name":254,"value":255},"Что такое HTTP и из чего состоит?","what-is-http-and-what-does-it-consist-of",{"name":257,"value":258},"Что такое заголовки в HTTP и зачем они нужны?","what-are-http-headers-and-why-do-we-need-them",{"name":260,"value":261},"Что такое параметры в HTTP?","what-are-http-parameters",{"name":263,"value":264},"Где находится HTML-код в структуре HTTP-ответа?","where-is-the-html-code-located-in-the-http-response-structure",{"name":266,"value":267},"Что такое HTML?","what-is-html",{"name":269,"value":270},"Чем отличаются 1.0, 1.1, 2.0, 3.0 версии HTTP?","what-are-the-differences-between-http-versions-1-0-1-1-2-0-and-3-0",{"name":272,"value":273},"Пользователь авторизован на сайте. Как сервер узнает об этом с последующими другими заходами, что «я – авторизованный пользователь»?","the-user-is-logged-in-on-the-website-how-does-the-server-know-that-i-am-an-authorized-user-when-the-user-logs-in-again",{"name":275,"value":276},"Что такое cookie?","what-is-a-cookie",{"name":278,"value":279},"Кто является инициатором записи cookie в браузере?","who-initiates-the-cookie-recording-in-the-browser",{"name":281,"value":282},"Есть ли возможность с клиента (с браузера) управлять cookie?","is-it-possible-to-manage-cookies-from-the-client-browser",{"name":284,"value":285},"Лайвкодинг","livecoding",{"name":287,"value":288},"Что вернёт следующий код? Object.create(null).hasOwnProperty('toString')","what-will-the-following-code-return-object-create-null-has-own-property-to-string",{"name":290,"value":291},"Всё, что идет по HTTPS – оно защищено?","is-everything-that-goes-through-https-secure",{"name":293,"value":294},"Все данные зашифрованы, используется https. Хакер взламывает dns и делает подмену одного ip на другой, на фишинговый сайт. В этом случае, злоумышленник может получить данные (логин \\ пароль)?","all-data-is-encrypted-https-is-used-let-s-assume-a-hacker-hacks-the-dns-and-makes-a-substitution-of-one-ip-for-another-a-phishing-site",{"name":296,"value":297},"Есть веб-приложение. Помимо HTTP, какие протоколы того же уровня (Application Layer) можно дополнительно использовать в веб-приложении в браузере?","there-is-a-web-application-in-addition-to-http-what-other-protocols-of-the-same-level-application-layer-can-be-used-in-the-web-application-in-browser",{"name":299,"value":300},"Как браузер парсит JavaScript и изображения при рендеринге?","how-the-browser-parses-javascript-and-images-when-rendering",{"name":302,"value":303},"Что происходит, когда HTTP прислал HTML? Что браузер дальше делает c HTML с учетом того, что она валидная?","what-happens-when-http-sends-html-what-does-the-browser-do-with-this-html-given-that-it-is-valid",{"name":305,"value":306},"Что в браузере блокирует рендеринг страницы?","what-is-blocking-the-page-rendering-in-the-browser",{"name":308,"value":309},"Что такое DOM в браузере? Что такое CSSOM?","what-is-dom-in-a-browser-what-is-cssom",{"name":311,"value":312},"Что является узлами в DOM?","what-are-nodes-in-the-dom",{"name":314,"value":315},"Из чего состоит CSSOM?","what-does-cssom-consist-of",{"name":317,"value":318},"Дан HTML-код. Какой будет цвет у текста «Some dummy text»?","the-html-code-is-given-what-will-be-the-color-of-the-some-dummy-text",{"name":320,"value":321},"Есть шаблон HTML и CSS кода. Какой будет цвет у текста «Таким образом, постоянное»?","there-is-a-template-for-html-and-css-code-what-color-will-the-text-thus-constant-have",{"name":323,"value":324},"Есть шаблон вложенного HTML кода. Какой будет цвет у текста «One more dummy text»?","there-is-a-template-for-embedded-html-code-what-will-be-the-color-of-the-one-more-dummy-text",{"name":326,"value":327},"Есть шаблон вложенного HTML кода. Будет ли display:block у body влиять на span?","there-is-a-template-for-embedded-html-code-will-there-be-a-display-does-bodys-block-affect-span",{"name":329,"value":330},"Есть HTML код. Будет ли font-weight на span влиять?","there-is-an-html-code-will-font-weight-affect-span",{"name":332,"value":333},"Flexbox и Grid, чем отличаются друг от друга?","what-are-the-differences-between-flexbox-and-grid",{"name":335,"value":336},"Заменяют ли Flexbox и Grid друг друга?","do-flexbox-and-grid-replace-each-other",{"name":338,"value":339},"Есть CSS и JS анимация. Какая между ними разница, что быстрее, что более удобно?","there-are-css-and-js-animations-what-is-the-difference-between-them-and-which-is-faster-and-more-convenient",{"name":341,"value":342},"Сборник задач","tasks",{"name":344,"value":345},"Какие способы объявления функции есть в JavaScript?","what-are-the-ways-to-declare-a-function-in-javascript",{"name":347,"value":348},"Что такое this в JavaScript?","what-is-this-in-javascript",{"name":350,"value":351},"Что такое Event Loop, как работает?","what-is-an-event-loop-and-how-does-it-work",{"name":353,"value":354},"Что будет, если вызвать typeof на необъявленной переменной?","what-happens-if-you-call-typeof-on-an-undeclared-variable",{"name":356,"value":357},"Что показывает оператор typeof в JavaScript?","what-does-the-typeof-operator-show-in-javascript",{"name":359,"value":360},"Какие типы данных существует в JavaScript?","what-types-of-data-exist-in-javascript",{"name":362,"value":363},"Какую структуру использовать для хранения упорядоченного списка строк в JavaScript?","what-is-the-best-structure-to-use-for-storing-an-ordered-list-of-strings-in-javascript",{"name":365,"value":366},"Что вернет typeof для массива?","what-will-typeof-return-for-an-array",{"name":368,"value":369},"Почему оператор typeof, применённый к массиву, возвращает объект?","why-does-the-typeof-operator-applied-to-an-array-return-an-object",{"name":371,"value":372},"Если нужно хранить список уникальных строк, какую структуру данных выбрать?","if-you-need-to-store-a-list-of-unique-strings-which-data-structure-should-i-choose",{"name":374,"value":375},"Что возвращает typeof для new Set в JavaScript?","what-does-typeof-return-for-new-set-in-javascript",{"name":377,"value":378},"Для чего нужен React, какие он решает проблемы?","what-is-react-used-for-and-what-problems-does-it-solve",{"name":380,"value":381},"Если убрать в React VDOM/Fiber, и вручную изменять DOM, разве это не оптимально?","if-you-remove-the-vdom-fiber-in-react-and-manually-change-the-dom-isn-t-that-optimal",{"name":383,"value":384},"Есть блок кода. Что в реальном DOM изменится после нажатия на кнопку?","there-is-a-block-of-code-what-changes-in-the-real-dom-after-clicking-the-button",{"name":386,"value":387},"Есть код, в котором список и кнопка. Что в реальном DOM изменится после нажатия на кнопку?","there-is-a-code-in-which-there-is-a-list-and-a-button-what-will-change-in-the-real-dom-after-clicking-on-the-button",{"name":389,"value":390},"Зачем нужен Redux (Mobx/Effector)? Зачем нужен менеджер состояния? Какие проблемы решает?","why-do-we-need-redux-mobx-effector-why-do-we-need-a-state-manager-what-problems-does-it-solve",{"name":392,"value":393},"Как диагностировать и исправить нежелательное изменение цвета фона по клику на кнопку, если исходный код сайта запутан и недоступен для прямого чтения?","how-can-diagnose-and-fix-unwanted-background-color-changes-when-clicking-on-a-button-if-the-source-code-of-the-site-is-confusing-and-inaccessible-to-direct-reading",{"name":395,"value":396},"Разрабатывал, взял закоммитил, запушил. Оказалось, что запушил не в ту ветку, точнее, коммит не в ту ветку. Какие действия?","developed-it-committed-it-and-launched-it-it-turned-out-that-i-had-pushed-it-to-the-wrong-branch-or-rather-the-commit-was-in-the-wrong-branch-what-actions",{"name":398,"value":399},"В git есть несколько вариантов слияния веток, какие? Чем отличаются?","git-has-several-options-for-merging-branches-which-ones-how-are-they-different",{"name":401,"value":402},"Какие существуют стратегии ветвления для работы команды? Что это такое?","what-are-the-branching-strategies-for-the-team-what-is-it",{"name":404,"value":405},"По каким характеристикам, ревьюер понимает, что данный код - хороший, а этот код - плохой?","how-does-a-reviewer-know-which-code-is-good-and-which-code-is-bad",{"name":407,"value":408},"Дан фрагмент bash-скрипта: cd ~; mkdir foo... Что в нем происходит?","here-is-a-fragment-of-a-bash-script-cd-mkdir-foo-what-is-happening-in-this-script",{"name":410,"value":411},"Дан фрагмент bash-скрипта: target=$(ps -Af | grep $1 | head -n 1)...","here-is-a-fragment-of-a-bash-script-target-ps-af-grep-1-head-n-1",{"name":413,"value":414},"Что такое алгоритмическая сложность?","what-is-algorithmic-complexity",{"name":416,"value":417},"Какая алгоритмическая сложность у \"быстрой сортировки\"?","what-is-the-algorithmic-complexity-of-quick-sort",{"name":419,"value":420},"Почему в JavaScript два объекта с одинаковым содержимым при сравнении возвращают false?","why-do-two-objects-with-the-same-content-return-false-when-compared-in-javascript",{"name":422,"value":423},"Каким способом может выполняться авторизация пользователя на сайте?","how-can-a-user-be-authorized-on-a-website",{"name":425,"value":426},"В чем разница между микро- и макро-тасками в JavaScript?","what-is-the-difference-between-micro-and-macro-tasks-in-javascript",{"name":428,"value":429},"В комнате три человека. Какова вероятность того, что хотя бы двое из них одного пола? То есть два и более.","there-are-three-people-in-the-room-what-is-the-probability-that-at-least-two-of-them-are-of-the-same-sex-that-is-two-or-more",{"name":431,"value":432},"Есть монета. Ее подбрасывают пять раз подряд. Каждый раз записывается, что выпало - орел или решка. Сколько разных последовательностей орлов и решек может при этом получиться?","there-is-a-coin-it-is-tossed-five-times-in-a-row-each-time-it-is-recorded-whether-it-lands-on-heads-or-tails-how-many-different-sequences-of-heads-and-tails-can-be-obtained",{"name":434,"value":435},"Как гарантированно найти лёгкую фальшивую монету среди 8 за минимальное число взвешиваний на чашечных весах?","how-can-you-guarantee-to-find-an-easy-fake-coin-among-8-in-the-minimum-number-of-weighings-on-a-balance-scale",{"name":437,"value":438},"Подготовка к тех.интервью","technical-interview",{"name":440,"value":441},"Верно ли утверждение, что злоумышленник, контролирующий роутер и прослушивающий трафик, может получить логины и пароли от сайтов, на которые заходит клиент?","is-it-true-that-an-attacker-who-controls-a-router-and-listens-to-traffic-can-obtain-logins-and-passwords-from-websites-that-a-client-visits",{"name":443,"value":444},"Что такое DNS, как DNS находит нужный IP-адрес?","what-is-dns-and-how-does-dns-find-the-correct-ip-address",{"name":446,"value":447},"Переменные объявлены следующим образом: a=3; b=«hello»;. Укажите правильное утверждение","variables-are-declared-as-follows-specify-the-correct-statement",{"name":449,"value":450},"Какой механизм лежит в основе оптимизации обновлений DOM в React?","what-is-the-underlying-mechanism-for-optimizing-dom-updates-in-react",{"name":452,"value":453},"Что мешает организовать централизованное состояние без менеджера состояния? Если организовать состояние механизмами реакта: контекстом, стейтом, в чем проблема? Что менеджеры состояния привносят?","what-prevents-you-from-organizing-a-centralized-state-without-a-state-manager-if-you-organize-the-state-using-react-context-and-state-mechanisms-what-is-the-problem-what-do-state-managers-add",[455],{"label":437,"slug":438,"to":456},"/technical-interview/where-to-begin",{"navigationList":458,"navigationSublist":464},[459,461],{"path":456,"isActive":101,"name":137,"icon":460,"isNavbarMobileDisabled":8},"material-symbols:visibility-outline-rounded",{"path":462,"isActive":8,"name":341,"icon":463,"isNavbarMobileDisabled":101},"/technical-interview/tasks","material-symbols:task-outline",[465,472,491,500,505,600,617,624,629,672,687,692],{"title":466,"list":467,"isOpened":101},"Bash",[468,470],{"name":407,"path":469,"isActive":101},"/technical-interview/tasks/here-is-a-fragment-of-a-bash-script-cd-mkdir-foo-what-is-happening-in-this-script",{"name":410,"path":471,"isActive":101},"/technical-interview/tasks/here-is-a-fragment-of-a-bash-script-target-ps-af-grep-1-head-n-1",{"title":473,"list":474,"isOpened":101},"CSS",[475,477,479,481,483,485,487,489],{"name":317,"path":476,"isActive":101},"/technical-interview/tasks/the-html-code-is-given-what-will-be-the-color-of-the-some-dummy-text",{"name":320,"path":478,"isActive":101},"/technical-interview/tasks/there-is-a-template-for-html-and-css-code-what-color-will-the-text-thus-constant-have",{"name":323,"path":480,"isActive":101},"/technical-interview/tasks/there-is-a-template-for-embedded-html-code-what-will-be-the-color-of-the-one-more-dummy-text",{"name":326,"path":482,"isActive":101},"/technical-interview/tasks/there-is-a-template-for-embedded-html-code-will-there-be-a-display-does-bodys-block-affect-span",{"name":329,"path":484,"isActive":101},"/technical-interview/tasks/there-is-an-html-code-will-font-weight-affect-span",{"name":332,"path":486,"isActive":101},"/technical-interview/tasks/what-are-the-differences-between-flexbox-and-grid",{"name":335,"path":488,"isActive":101},"/technical-interview/tasks/do-flexbox-and-grid-replace-each-other",{"name":338,"path":490,"isActive":101},"/technical-interview/tasks/there-are-css-and-js-animations-what-is-the-difference-between-them-and-which-is-faster-and-more-convenient",{"title":492,"list":493,"isOpened":101},"Git",[494,496,498],{"name":395,"path":495,"isActive":101},"/technical-interview/tasks/developed-it-committed-it-and-launched-it-it-turned-out-that-i-had-pushed-it-to-the-wrong-branch-or-rather-the-commit-was-in-the-wrong-branch-what-actions",{"name":398,"path":497,"isActive":101},"/technical-interview/tasks/git-has-several-options-for-merging-branches-which-ones-how-are-they-different",{"name":401,"path":499,"isActive":101},"/technical-interview/tasks/what-are-the-branching-strategies-for-the-team-what-is-it",{"title":501,"list":502,"isOpened":101},"HTML",[503],{"name":266,"path":504,"isActive":101},"/technical-interview/tasks/what-is-html",{"title":506,"list":507,"isOpened":101},"JavaScript",[508,510,512,514,516,518,520,522,524,526,528,530,532,534,536,538,540,542,544,546,548,550,552,554,556,558,560,562,564,566,568,570,572,574,576,578,580,582,584,586,588,590,592,594,596,598],{"name":149,"path":509,"isActive":101},"/technical-interview/tasks/prototype-what-logical-values-will-be-received-in-console-log",{"name":140,"path":511,"isActive":101},"/technical-interview/tasks/why-is-it-dangerous-to-write-directly-to-the-prototypes-of-basic-types",{"name":287,"path":513,"isActive":101},"/technical-interview/tasks/what-will-the-following-code-return-object-create-null-has-own-property-to-string",{"name":170,"path":515,"isActive":101},"/technical-interview/tasks/what-value-will-the-console-output-with-object-property",{"name":173,"path":517,"isActive":101},"/technical-interview/tasks/what-will-be-displayed-in-console-log-arr-0-arr-0",{"name":209,"path":519,"isActive":101},"/technical-interview/tasks/what-will-console-log-output-as-a-result-of-executing-the-while-loop",{"name":212,"path":521,"isActive":101},"/technical-interview/tasks/there-is-a-function-and-an-object-write-all-the-ways-you-know-to-output-the-value-of-x-from-an-object-in-the-console-using-the-function",{"name":227,"path":523,"isActive":101},"/technical-interview/tasks/what-will-the-book-get-upper-name-method-return",{"name":446,"path":525,"isActive":101},"/technical-interview/tasks/variables-are-declared-as-follows-specify-the-correct-statement",{"name":233,"path":527,"isActive":101},"/technical-interview/tasks/what-will-the-console-display-if-a-property-is-assigned-to-an-array-using-a-positive-string-index",{"name":215,"path":529,"isActive":101},"/technical-interview/tasks/what-will-the-console-display-if-a-property-is-assigned-to-an-array-using-a-negative-string-index",{"name":218,"path":531,"isActive":101},"/technical-interview/tasks/what-will-the-console-output-if-an-array-element-is-deleted-using-the-delete-operator",{"name":134,"path":533,"isActive":101},"/technical-interview/tasks/what-this-code-will-return-typeof-function",{"name":236,"path":535,"isActive":101},"/technical-interview/tasks/what-will-happen-when-an-object-is-passed-as-an-argument-to-a-function-and-the-code-is-executed",{"name":344,"path":537,"isActive":101},"/technical-interview/tasks/what-are-the-ways-to-declare-a-function-in-javascript",{"name":347,"path":539,"isActive":101},"/technical-interview/tasks/what-is-this-in-javascript",{"name":350,"path":541,"isActive":101},"/technical-interview/tasks/what-is-an-event-loop-and-how-does-it-work",{"name":353,"path":543,"isActive":101},"/technical-interview/tasks/what-happens-if-you-call-typeof-on-an-undeclared-variable",{"name":356,"path":545,"isActive":101},"/technical-interview/tasks/what-does-the-typeof-operator-show-in-javascript",{"name":359,"path":547,"isActive":101},"/technical-interview/tasks/what-types-of-data-exist-in-javascript",{"name":362,"path":549,"isActive":101},"/technical-interview/tasks/what-is-the-best-structure-to-use-for-storing-an-ordered-list-of-strings-in-javascript",{"name":365,"path":551,"isActive":101},"/technical-interview/tasks/what-will-typeof-return-for-an-array",{"name":368,"path":553,"isActive":101},"/technical-interview/tasks/why-does-the-typeof-operator-applied-to-an-array-return-an-object",{"name":371,"path":555,"isActive":101},"/technical-interview/tasks/if-you-need-to-store-a-list-of-unique-strings-which-data-structure-should-i-choose",{"name":374,"path":557,"isActive":101},"/technical-interview/tasks/what-does-typeof-return-for-new-set-in-javascript",{"name":419,"path":559,"isActive":101},"/technical-interview/tasks/why-do-two-objects-with-the-same-content-return-false-when-compared-in-javascript",{"name":425,"path":561,"isActive":101},"/technical-interview/tasks/what-is-the-difference-between-micro-and-macro-tasks-in-javascript",{"name":158,"path":563,"isActive":101},"/technical-interview/tasks/arr-push-0-will-affect-the-array-in-the-same-way-as-if-we-performed",{"name":176,"path":565,"isActive":101},"/technical-interview/tasks/returns-an-array-from-1-to-n-replacing-numbers-that-are-multiples-of-3-with-fizz-numbers-that-are-multiples-of-5-with-buzz-and-numbers-that-are-multiples-of-both-3-and-5-with-fizzbuzz",{"name":161,"path":567,"isActive":101},"/technical-interview/tasks/the-string-one-two-three-four-five-is-given-it-is-necessary-to-make-a-nested-object-out-of-the-string",{"name":191,"path":569,"isActive":101},"/technical-interview/tasks/given-a-tree-nested-object-it-is-necessary-to-find-the-sum-of-all-vertices",{"name":167,"path":571,"isActive":101},"/technical-interview/tasks/for-each-nested-object-you-need-to-add-the-level-property-which-is-equal-to-a-number-the-nesting-number",{"name":194,"path":573,"isActive":101},"/technical-interview/tasks/for-each-branch-of-the-tree-write-down-the-nesting-number-of-this-branch",{"name":185,"path":575,"isActive":101},"/technical-interview/tasks/there-is-an-array-containing-objects-with-dates-that-need-to-be-sorted-by-date",{"name":197,"path":577,"isActive":101},"/technical-interview/tasks/there-are-words-in-the-array-it-is-necessary-to-determine-whether-they-consist-of-the-same-letters",{"name":203,"path":579,"isActive":101},"/technical-interview/tasks/there-is-a-string-consisting-of-different-brackets-it-is-necessary-to-check-whether-all-are-closed",{"name":155,"path":581,"isActive":101},"/technical-interview/tasks/find-non-repeating-numbers-in-an-array",{"name":206,"path":583,"isActive":101},"/technical-interview/tasks/write-a-function-that-will-make-an-object-out-of-an-array",{"name":179,"path":585,"isActive":101},"/technical-interview/tasks/checks-whether-two-strings-are-anagrams-of-each-other",{"name":152,"path":587,"isActive":101},"/technical-interview/tasks/odd-numbers-should-be-sorted-in-ascending-order-and-even-numbers-should-remain-in-their-original-positions",{"name":182,"path":589,"isActive":101},"/technical-interview/tasks/determines-whether-a-word-is-a-palindrome",{"name":224,"path":591,"isActive":101},"/technical-interview/tasks/flattening-the-array",{"name":188,"path":593,"isActive":101},"/technical-interview/tasks/implement-a-function-that-accepts-arguments-1-b-1c-and-the-return-string-1-b-1c",{"name":230,"path":595,"isActive":101},"/technical-interview/tasks/string-compression",{"name":221,"path":597,"isActive":101},"/technical-interview/tasks/unifying-values-in-an-array",{"name":200,"path":599,"isActive":101},"/technical-interview/tasks/the-numbers-from-1-to-100-are-in-the-array-they-are-randomly-mixed-but-it-lacks-one-number-from-this-sequence-it-is-necessary-to-find-him",{"title":601,"list":602,"isOpened":101},"React",[603,605,607,609,611,613,615],{"name":377,"path":604,"isActive":101},"/technical-interview/tasks/what-is-react-used-for-and-what-problems-does-it-solve",{"name":449,"path":606,"isActive":101},"/technical-interview/tasks/what-is-the-underlying-mechanism-for-optimizing-dom-updates-in-react",{"name":380,"path":608,"isActive":101},"/technical-interview/tasks/if-you-remove-the-vdom-fiber-in-react-and-manually-change-the-dom-isn-t-that-optimal",{"name":383,"path":610,"isActive":101},"/technical-interview/tasks/there-is-a-block-of-code-what-changes-in-the-real-dom-after-clicking-the-button",{"name":386,"path":612,"isActive":101},"/technical-interview/tasks/there-is-a-code-in-which-there-is-a-list-and-a-button-what-will-change-in-the-real-dom-after-clicking-on-the-button",{"name":389,"path":614,"isActive":101},"/technical-interview/tasks/why-do-we-need-redux-mobx-effector-why-do-we-need-a-state-manager-what-problems-does-it-solve",{"name":452,"path":616,"isActive":101},"/technical-interview/tasks/what-prevents-you-from-organizing-a-centralized-state-without-a-state-manager-if-you-organize-the-state-using-react-context-and-state-mechanisms-what-is-the-problem-what-do-state-managers-add",{"title":618,"list":619,"isOpened":101},"Алгоритмы",[620,622],{"name":413,"path":621,"isActive":101},"/technical-interview/tasks/what-is-algorithmic-complexity",{"name":416,"path":623,"isActive":101},"/technical-interview/tasks/what-is-the-algorithmic-complexity-of-quick-sort",{"title":625,"list":626,"isOpened":101},"Дебаггинг",[627],{"name":392,"path":628,"isActive":101},"/technical-interview/tasks/how-can-diagnose-and-fix-unwanted-background-color-changes-when-clicking-on-a-button-if-the-source-code-of-the-site-is-confusing-and-inaccessible-to-direct-reading",{"title":630,"list":631,"isOpened":101},"Компьютерные сети",[632,634,636,638,640,642,644,646,648,650,652,654,656,658,660,662,664,666,668,670],{"name":239,"path":633,"isActive":101},"/technical-interview/tasks/how-does-the-browser-know-where-to-get-the-website-after-entering-the-domain",{"name":443,"path":635,"isActive":101},"/technical-interview/tasks/what-is-dns-and-how-does-dns-find-the-correct-ip-address",{"name":242,"path":637,"isActive":101},"/technical-interview/tasks/how-does-a-domain-get-into-the-dns-mapping-table-domain-ip",{"name":245,"path":639,"isActive":101},"/technical-interview/tasks/how-does-a-browser-decide-whether-to-open-a-tcp-or-udp-connection",{"name":248,"path":641,"isActive":101},"/technical-interview/tasks/key-differences-between-tcp-and-udp",{"name":251,"path":643,"isActive":101},"/technical-interview/tasks/tcp-ip-who-is-tcp-and-who-is-ip-in-this-case",{"name":254,"path":645,"isActive":101},"/technical-interview/tasks/what-is-http-and-what-does-it-consist-of",{"name":257,"path":647,"isActive":101},"/technical-interview/tasks/what-are-http-headers-and-why-do-we-need-them",{"name":260,"path":649,"isActive":101},"/technical-interview/tasks/what-are-http-parameters",{"name":263,"path":651,"isActive":101},"/technical-interview/tasks/where-is-the-html-code-located-in-the-http-response-structure",{"name":269,"path":653,"isActive":101},"/technical-interview/tasks/what-are-the-differences-between-http-versions-1-0-1-1-2-0-and-3-0",{"name":272,"path":655,"isActive":101},"/technical-interview/tasks/the-user-is-logged-in-on-the-website-how-does-the-server-know-that-i-am-an-authorized-user-when-the-user-logs-in-again",{"name":275,"path":657,"isActive":101},"/technical-interview/tasks/what-is-a-cookie",{"name":278,"path":659,"isActive":101},"/technical-interview/tasks/who-initiates-the-cookie-recording-in-the-browser",{"name":281,"path":661,"isActive":101},"/technical-interview/tasks/is-it-possible-to-manage-cookies-from-the-client-browser",{"name":440,"path":663,"isActive":101},"/technical-interview/tasks/is-it-true-that-an-attacker-who-controls-a-router-and-listens-to-traffic-can-obtain-logins-and-passwords-from-websites-that-a-client-visits",{"name":290,"path":665,"isActive":101},"/technical-interview/tasks/is-everything-that-goes-through-https-secure",{"name":293,"path":667,"isActive":101},"/technical-interview/tasks/all-data-is-encrypted-https-is-used-let-s-assume-a-hacker-hacks-the-dns-and-makes-a-substitution-of-one-ip-for-another-a-phishing-site",{"name":296,"path":669,"isActive":101},"/technical-interview/tasks/there-is-a-web-application-in-addition-to-http-what-other-protocols-of-the-same-level-application-layer-can-be-used-in-the-web-application-in-browser",{"name":422,"path":671,"isActive":101},"/technical-interview/tasks/how-can-a-user-be-authorized-on-a-website",{"title":673,"list":674,"isOpened":101},"Отрисовка в браузере",[675,677,679,681,683,685],{"name":302,"path":676,"isActive":101},"/technical-interview/tasks/what-happens-when-http-sends-html-what-does-the-browser-do-with-this-html-given-that-it-is-valid",{"name":299,"path":678,"isActive":101},"/technical-interview/tasks/how-the-browser-parses-javascript-and-images-when-rendering",{"name":305,"path":680,"isActive":101},"/technical-interview/tasks/what-is-blocking-the-page-rendering-in-the-browser",{"name":308,"path":682,"isActive":101},"/technical-interview/tasks/what-is-dom-in-a-browser-what-is-cssom",{"name":311,"path":684,"isActive":101},"/technical-interview/tasks/what-are-nodes-in-the-dom",{"name":314,"path":686,"isActive":101},"/technical-interview/tasks/what-does-cssom-consist-of",{"title":688,"list":689,"isOpened":101},"Ревью кода",[690],{"name":404,"path":691,"isActive":101},"/technical-interview/tasks/how-does-a-reviewer-know-which-code-is-good-and-which-code-is-bad",{"title":693,"list":694,"isOpened":101},"Теория вероятности",[695,697,699],{"name":428,"path":696,"isActive":101},"/technical-interview/tasks/there-are-three-people-in-the-room-what-is-the-probability-that-at-least-two-of-them-are-of-the-same-sex-that-is-two-or-more",{"name":431,"path":698,"isActive":101},"/technical-interview/tasks/there-is-a-coin-it-is-tossed-five-times-in-a-row-each-time-it-is-recorded-whether-it-lands-on-heads-or-tails-how-many-different-sequences-of-heads-and-tails-can-be-obtained",{"name":434,"path":700,"isActive":101},"/technical-interview/tasks/how-can-you-guarantee-to-find-an-easy-fake-coin-among-8-in-the-minimum-number-of-weighings-on-a-balance-scale",{"cooperation":702,"copyright":705,"reportError":706,"socialNetwork":708},{"link":703,"title":704},"https://t.me/baurinanton","Сотрудничество","© “GOOD WEB JOB!”",{"label":707,"link":703},"Сообщить об ошибке",{"label":709,"socialNetworkList":710},"Мы в соцсетях:",[711,714,717],{"icon":26,"link":712,"title":713},"https://max.ru/u/f9LHodD0cOKMaukdnnahTeL5pwvjrPfUaZ4S8_1rsNy9I9qsmc9Ar3kP_y8","Max",{"icon":715,"link":703,"title":716},"ic:baseline-telegram","Telegram",{"icon":718,"link":719,"title":720},"ri:vk-fill","https://vk.com/baurinanton","VK",{"data":722,"body":723},{},{"type":724,"children":725},"root",[726],{"type":727,"tag":728,"props":729,"children":730},"element","p",{},[731],{"type":732,"value":113},"text",{"data":734,"body":735},{},{"type":724,"children":736},[737],{"type":727,"tag":728,"props":738,"children":739},{},[740],{"type":732,"value":100},{"data":742,"body":743},{},{"type":724,"children":744},[745],{"type":727,"tag":728,"props":746,"children":747},{},[748],{"type":732,"value":104},{"data":750,"body":751},{},{"type":724,"children":752},[753,767,779],{"type":727,"tag":728,"props":754,"children":755},{},[756,758,765],{"type":732,"value":757},"Идея: создаётся небольшое хранилище, чтение делается через хук с селектором, обновление — через функцию ",{"type":727,"tag":759,"props":760,"children":762},"code",{"className":761},[],[763],{"type":732,"value":764},"set",{"type":732,"value":766},".",{"type":727,"tag":768,"props":769,"children":773},"pre",{"className":770,"code":772,"language":732},[771],"language-text","import { create } from \"zustand\";\n\nconst useUserStore = create((set) => ({\n  user: null,\n  setUser: (user) => set({ user }),\n}));\n\nfunction Header() {\n  const user = useUserStore((s) => s.user);\n  return \u003Cdiv>Hello, {user ? user.name : \"Loading...\"}\u003C/div>;\n}\n\n// Загрузка данных:\nfetch(\"/api/me\")\n  .then((r) => r.json())\n  .then((user) => useUserStore.getState().setUser(user));\n",[774],{"type":727,"tag":759,"props":775,"children":777},{"__ignoreMap":776},"",[778],{"type":732,"value":772},{"type":727,"tag":728,"props":780,"children":781},{},[782],{"type":732,"value":783},"Ключевая мысль: компонент получает данные напрямую из хранилища и обновляется, когда меняется выбранный “срез” состояния.",{"data":785,"body":786},{},{"type":724,"children":787},[788],{"type":727,"tag":728,"props":789,"children":790},{},[791],{"type":732,"value":110},{"data":793,"body":794},{},{"type":724,"children":795},[796],{"type":727,"tag":728,"props":797,"children":798},{},[799],{"type":732,"value":107},{"data":801,"body":802},{},{"type":724,"children":803},[804],{"type":727,"tag":728,"props":805,"children":806},{},[807],{"type":732,"value":111},{"data":809,"body":810},{},{"type":724,"children":811},[812],{"type":727,"tag":728,"props":813,"children":814},{},[815,821],{"type":727,"tag":816,"props":817,"children":818},"strong",{},[819],{"type":732,"value":820},"Правильный ответ: 2",{"type":732,"value":822}," - для централизованного управления состоянием приложения, что решает проблемы рассинхронизации данных, сложного отслеживания изменений и 'пропс-дриллинга' в больших приложениях.",{"data":824,"body":825},{},{"type":724,"children":826},[827],{"type":727,"tag":728,"props":828,"children":829},{},[830],{"type":732,"value":831},"Состояние (state) — это данные, которые меняются со временем и влияют на то, что видит пользователь: авторизация, профиль, корзина, фильтры, результаты запросов, настройки интерфейса.",{"data":833,"body":834},{},{"type":724,"children":835},[836],{"type":727,"tag":837,"props":838,"children":839},"ol",{},[840,846,851,856],{"type":727,"tag":841,"props":842,"children":843},"li",{},[844],{"type":732,"value":845},"Сначала состояние хранится локально в компонентах.",{"type":727,"tag":841,"props":847,"children":848},{},[849],{"type":732,"value":850},"Затем одни и те же данные становятся нужны нескольким веткам интерфейса.",{"type":727,"tag":841,"props":852,"children":853},{},[854],{"type":732,"value":855},"Начинается передача данных “сверху вниз” через несколько уровней компонентов (prop drilling).",{"type":727,"tag":841,"props":857,"children":858},{},[859],{"type":732,"value":860},"Появляется риск рассинхронизации: разные части интерфейса обновляют похожие данные по-разному и в разное время.",{"data":862,"body":863},{},{"type":724,"children":864},[865],{"type":727,"tag":728,"props":866,"children":867},{},[868],{"type":732,"value":25},{"data":870,"body":871},{},{"type":724,"children":872},[873],{"type":727,"tag":874,"props":875,"children":876},"ul",{},[877,882,887,892],{"type":727,"tag":841,"props":878,"children":879},{},[880],{"type":732,"value":881},"Единый источник истины для общих данных (часто это единое хранилище, “store”).",{"type":727,"tag":841,"props":883,"children":884},{},[885],{"type":732,"value":886},"Явные способы изменения состояния: через события/действия и правила обновления (например, редьюсеры).",{"type":727,"tag":841,"props":888,"children":889},{},[890],{"type":732,"value":891},"Реактивные подписки: при изменении данных связанные части интерфейса обновляются автоматически.",{"type":727,"tag":841,"props":893,"children":894},{},[895],{"type":732,"value":896},"Упрощение диагностики: становится проще понять, что произошло (событие/действие) и по какому правилу изменились данные.",{"data":898,"body":899},{},{"type":724,"children":900},[901],{"type":727,"tag":728,"props":902,"children":903},{},[904],{"type":732,"value":36},{"data":906,"body":907},{},{"type":724,"children":908},[909,922,931,936,954,959],{"type":727,"tag":728,"props":910,"children":911},{},[912,914,920],{"type":732,"value":913},"Ниже показана упрощённая ситуация: значение ",{"type":727,"tag":759,"props":915,"children":917},{"className":916},[],[918],{"type":732,"value":919},"user",{"type":732,"value":921}," требуется и вверху, и глубоко внутри дерева, а также участвует в загрузке данных.",{"type":727,"tag":768,"props":923,"children":926},{"className":924,"code":925,"language":732},[771],"// Пример: данные прокидываются через несколько уровней,\n// хотя промежуточным компонентам они не нужны.\n\nfunction App() {\n  const [user, setUser] = React.useState(null);\n\n  React.useEffect(() => {\n    fetch(\"/api/me\")\n      .then((r) => r.json())\n      .then(setUser);\n  }, []);\n\n  return (\n    \u003CLayout user={user}>\n      \u003CPage user={user} />\n    \u003C/Layout>\n  );\n}\n\nfunction Layout({ user, children }) {\n  return (\n    \u003Cdiv>\n      \u003CHeader user={user} />\n      {children}\n    \u003C/div>\n  );\n}\n\nfunction Page({ user }) {\n  return \u003CProfileCard user={user} />;\n}\n\nfunction ProfileCard({ user }) {\n  if (!user) return \u003Cspan>Loading...\u003C/span>;\n  return \u003Cdiv>Hello, {user.name}\u003C/div>;\n}\n",[927],{"type":727,"tag":759,"props":928,"children":929},{"__ignoreMap":776},[930],{"type":732,"value":925},{"type":727,"tag":728,"props":932,"children":933},{},[934],{"type":732,"value":935},"Проблемы такого подхода в больших приложениях:",{"type":727,"tag":874,"props":937,"children":938},{},[939,944,949],{"type":727,"tag":841,"props":940,"children":941},{},[942],{"type":732,"value":943},"Сложно менять структуру дерева компонентов: приходится “протягивать” пропсы через новые уровни.",{"type":727,"tag":841,"props":945,"children":946},{},[947],{"type":732,"value":948},"Трудно гарантировать единообразное обновление, если похожие данные начинают храниться в нескольких местах.",{"type":727,"tag":841,"props":950,"children":951},{},[952],{"type":732,"value":953},"Сложно отлаживать, кто и когда изменил данные, если обновления распределены по множеству компонентов.",{"type":727,"tag":728,"props":955,"children":956},{},[957],{"type":732,"value":958},"Схематично:",{"type":727,"tag":768,"props":960,"children":963},{"className":961,"code":962,"language":732},[771],"Без менеджера:\nApp (state)\n  ├─ Layout (просто пересылает user)\n  │    └─ Header (читает user)\n  └─ Page (просто пересылает user)\n       └─ ProfileCard (читает user)\n\nС менеджером:\nGlobal Store (state)\n  ├─ Header (подписка на store)\n  └─ ProfileCard (подписка на store)\n",[964],{"type":727,"tag":759,"props":965,"children":966},{"__ignoreMap":776},[967],{"type":732,"value":962},{"data":969,"body":970},{},{"type":724,"children":971},[972,1000,1009],{"type":727,"tag":728,"props":973,"children":974},{},[975,977,983,985,991,993,999],{"type":732,"value":976},"Идея: состояние хранится в ",{"type":727,"tag":759,"props":978,"children":980},{"className":979},[],[981],{"type":732,"value":982},"store",{"type":732,"value":984},", изменение инициируется через ",{"type":727,"tag":759,"props":986,"children":988},{"className":987},[],[989],{"type":732,"value":990},"dispatch(action)",{"type":732,"value":992},", а новый state вычисляется функцией ",{"type":727,"tag":759,"props":994,"children":996},{"className":995},[],[997],{"type":732,"value":998},"reducer",{"type":732,"value":766},{"type":727,"tag":768,"props":1001,"children":1004},{"className":1002,"code":1003,"language":732},[771],"import { createStore } from \"redux\";\n\n// Action (описание “что произошло”)\nconst setUser = (user) => ({ type: \"user/set\", payload: user });\n\n// Reducer (правило “как меняется state”)\nfunction reducer(state = { user: null }, action) {\n  switch (action.type) {\n    case \"user/set\":\n      return { ...state, user: action.payload };\n    default:\n      return state;\n  }\n}\n\nexport const store = createStore(reducer);\n\n// Где-то в коде загрузки данных:\nfetch(\"/api/me\")\n  .then((r) => r.json())\n  .then((user) => store.dispatch(setUser(user)));\n\n// В UI (псевдокод): подписка на store и чтение store.getState()\n",[1005],{"type":727,"tag":759,"props":1006,"children":1007},{"__ignoreMap":776},[1008],{"type":732,"value":1003},{"type":727,"tag":728,"props":1010,"children":1011},{},[1012,1014,1019],{"type":732,"value":1013},"Ключевая мысль: компонентам не требуется получать ",{"type":727,"tag":759,"props":1015,"children":1017},{"className":1016},[],[1018],{"type":732,"value":919},{"type":732,"value":1020}," через цепочку пропсов, потому что чтение идёт из общего хранилища.",{"data":1022,"body":1023},{},{"type":724,"children":1024},[1025],{"type":727,"tag":728,"props":1026,"children":1027},{},[1028],{"type":732,"value":48},{"data":1030,"body":1031},{},{"type":724,"children":1032},[1033,1038,1047],{"type":727,"tag":728,"props":1034,"children":1035},{},[1036],{"type":732,"value":1037},"Идея: есть “наблюдаемые” данные, а UI автоматически обновляется, если были использованы значения, которые изменились.",{"type":727,"tag":768,"props":1039,"children":1042},{"className":1040,"code":1041,"language":732},[771],"import { makeAutoObservable } from \"mobx\";\nimport { observer } from \"mobx-react-lite\";\n\nclass UserStore {\n  user = null;\n\n  constructor() {\n    makeAutoObservable(this);\n  }\n\n  setUser(user) {\n    this.user = user;\n  }\n\n  get userName() {\n    return this.user ? this.user.name : \"Loading...\";\n  }\n}\n\nexport const userStore = new UserStore();\n\n// UI: компонент реагирует на изменения используемых полей\nexport const Header = observer(() => {\n  return \u003Cdiv>Hello, {userStore.userName}\u003C/div>;\n});\n",[1043],{"type":727,"tag":759,"props":1044,"children":1045},{"__ignoreMap":776},[1046],{"type":732,"value":1041},{"type":727,"tag":728,"props":1048,"children":1049},{},[1050,1052,1058],{"type":732,"value":1051},"Ключевая мысль: производные значения (например, ",{"type":727,"tag":759,"props":1053,"children":1055},{"className":1054},[],[1056],{"type":732,"value":1057},"userName",{"type":732,"value":1059},") удобно держать рядом с моделью и получать автоматически обновляемый UI.",{"data":1061,"body":1062},{},{"type":724,"children":1063},[1064,1076,1085],{"type":727,"tag":728,"props":1065,"children":1066},{},[1067,1069,1074],{"type":732,"value":1068},"Идея: изменения описываются как события, а ",{"type":727,"tag":759,"props":1070,"children":1072},{"className":1071},[],[1073],{"type":732,"value":982},{"type":732,"value":1075}," обновляется реактивно в ответ на эти события.",{"type":727,"tag":768,"props":1077,"children":1080},{"className":1078,"code":1079,"language":732},[771],"import { createEvent, createStore } from \"effector\";\n\n// Событие: “что произошло”\nconst userLoaded = createEvent();\n\n// Store: “где хранятся данные”\nconst $user = createStore(null)\n  .on(userLoaded, (_, user) => user);\n\n// Где-то в коде загрузки:\nfetch(\"/api/me\")\n  .then((r) => r.json())\n  .then(userLoaded);\n\n// UI (псевдокод): подписка на $user через bindings для фреймворка\n",[1081],{"type":727,"tag":759,"props":1082,"children":1083},{"__ignoreMap":776},[1084],{"type":732,"value":1079},{"type":727,"tag":728,"props":1086,"children":1087},{},[1088],{"type":732,"value":1089},"Ключевая мысль: состояние меняется не “напрямую”, а через поток событий и описанные правила реакции store.",{"data":1091,"body":1092},{},{"type":724,"children":1093},[1094,1099,1117,1122],{"type":727,"tag":728,"props":1095,"children":1096},{},[1097],{"type":732,"value":1098},"Менеджер состояния обычно оправдан, когда:",{"type":727,"tag":874,"props":1100,"children":1101},{},[1102,1107,1112],{"type":727,"tag":841,"props":1103,"children":1104},{},[1105],{"type":732,"value":1106},"Одни и те же данные используются во многих независимых компонентах (например, пользователь, права, корзина).",{"type":727,"tag":841,"props":1108,"children":1109},{},[1110],{"type":732,"value":1111},"Есть сложные сценарии обновлений (несколько источников событий, асинхронные запросы, зависимые вычисления).",{"type":727,"tag":841,"props":1113,"children":1114},{},[1115],{"type":732,"value":1116},"Нужны единые правила, чтобы понимать “кто изменил состояние и почему” (события/действия + правила обновления).",{"type":727,"tag":728,"props":1118,"children":1119},{},[1120],{"type":732,"value":1121},"Часто можно обойтись без отдельной библиотеки, когда:",{"type":727,"tag":874,"props":1123,"children":1124},{},[1125,1130,1135],{"type":727,"tag":841,"props":1126,"children":1127},{},[1128],{"type":732,"value":1129},"Состояние локальное и используется внутри одного компонента или небольшой ветки.",{"type":727,"tag":841,"props":1131,"children":1132},{},[1133],{"type":732,"value":1134},"Поднятия состояния на уровень выше достаточно, и цепочки передачи не становятся длинными.",{"type":727,"tag":841,"props":1136,"children":1137},{},[1138,1140,1146],{"type":732,"value":1139},"React Context + ",{"type":727,"tag":759,"props":1141,"children":1143},{"className":1142},[],[1144],{"type":732,"value":1145},"useReducer",{"type":732,"value":1147}," покрывают потребности без сложных потоков данных.",{"data":1149,"body":1150},{},{"type":724,"children":1151},[1152],{"type":727,"tag":728,"props":1153,"children":1154},{},[1155],{"type":732,"value":94},{"data":1157,"body":1158},{},{"type":724,"children":1159},[1160],{"type":727,"tag":1161,"props":1162,"children":1163},"table",{},[1164,1193],{"type":727,"tag":1165,"props":1166,"children":1167},"thead",{},[1168],{"type":727,"tag":1169,"props":1170,"children":1171},"tr",{},[1172,1178,1183,1188],{"type":727,"tag":1173,"props":1174,"children":1175},"th",{},[1176],{"type":732,"value":1177},"Библиотека",{"type":727,"tag":1173,"props":1179,"children":1180},{},[1181],{"type":732,"value":1182},"Основная идея",{"type":727,"tag":1173,"props":1184,"children":1185},{},[1186],{"type":732,"value":1187},"Как меняется состояние",{"type":727,"tag":1173,"props":1189,"children":1190},{},[1191],{"type":732,"value":1192},"Типичный плюс",{"type":727,"tag":1194,"props":1195,"children":1196},"tbody",{},[1197,1233,1256,1279],{"type":727,"tag":1169,"props":1198,"children":1199},{},[1200,1206,1211,1228],{"type":727,"tag":1201,"props":1202,"children":1203},"td",{},[1204],{"type":732,"value":1205},"Redux",{"type":727,"tag":1201,"props":1207,"children":1208},{},[1209],{"type":732,"value":1210},"Единое хранилище + явные действия и правила",{"type":727,"tag":1201,"props":1212,"children":1213},{},[1214,1219,1221,1226],{"type":727,"tag":759,"props":1215,"children":1217},{"className":1216},[],[1218],{"type":732,"value":990},{"type":732,"value":1220}," → ",{"type":727,"tag":759,"props":1222,"children":1224},{"className":1223},[],[1225],{"type":732,"value":998},{"type":732,"value":1227}," возвращает новый state",{"type":727,"tag":1201,"props":1229,"children":1230},{},[1231],{"type":732,"value":1232},"Предсказуемость и единый стиль изменений",{"type":727,"tag":1169,"props":1234,"children":1235},{},[1236,1241,1246,1251],{"type":727,"tag":1201,"props":1237,"children":1238},{},[1239],{"type":732,"value":1240},"MobX",{"type":727,"tag":1201,"props":1242,"children":1243},{},[1244],{"type":732,"value":1245},"Реактивные данные и вычисления",{"type":727,"tag":1201,"props":1247,"children":1248},{},[1249],{"type":732,"value":1250},"Изменение наблюдаемых данных, UI реагирует автоматически",{"type":727,"tag":1201,"props":1252,"children":1253},{},[1254],{"type":732,"value":1255},"Меньше “связующего” кода вокруг derived-логики",{"type":727,"tag":1169,"props":1257,"children":1258},{},[1259,1264,1269,1274],{"type":727,"tag":1201,"props":1260,"children":1261},{},[1262],{"type":732,"value":1263},"Effector",{"type":727,"tag":1201,"props":1265,"children":1266},{},[1267],{"type":732,"value":1268},"События и реактивные stores",{"type":727,"tag":1201,"props":1270,"children":1271},{},[1272],{"type":732,"value":1273},"Store обновляется через события и реакции",{"type":727,"tag":1201,"props":1275,"children":1276},{},[1277],{"type":732,"value":1278},"Явные потоки событий и хорошая композиция",{"type":727,"tag":1169,"props":1280,"children":1281},{},[1282,1287,1292,1303],{"type":727,"tag":1201,"props":1283,"children":1284},{},[1285],{"type":732,"value":1286},"Zustand",{"type":727,"tag":1201,"props":1288,"children":1289},{},[1290],{"type":732,"value":1291},"Минимальное хранилище",{"type":727,"tag":1201,"props":1293,"children":1294},{},[1295,1301],{"type":727,"tag":759,"props":1296,"children":1298},{"className":1297},[],[1299],{"type":732,"value":1300},"set(...)",{"type":732,"value":1302},", подписка через хук с селектором",{"type":727,"tag":1201,"props":1304,"children":1305},{},[1306],{"type":732,"value":1307},"Простота и малое количество абстракций",{"data":1309,"body":1310},{},{"type":724,"children":1311},[1312],{"type":727,"tag":728,"props":1313,"children":1314},{},[1315],{"type":732,"value":85},1775735655417]