[{"data":1,"prerenderedAt":1435},["ShallowReactive",2],{"$fbVf6WkTFlb3FIe10gv7tQiNO0zpqqazhj1JTNdlABII":3,"$fMMUdSFktwQFqMVGPrTtt3EC5yheBp7PzwIqznamFcMo":104,"$f1Prj1xEczHja_-L7FyIGgRHd5_cSWHo7r6AE5aheAik":107,"$fc0LoAJgqXDLbKKd2JS_NpM4SuzBK8EycUXINSg09CKU":433,"$fM3ea55k6lKMPOTM84llDB26VSQDVVbxiQuSBFQw9P_c":436,"$fI5fDmvm-5tr9wcH0eHaKZa1j3y_FQIQaHHPqbZxAHJE":680,"mdc-c5dg2m-key":700,"mdc-cbdk9m-key":740,"mdc-93y4en-key":748,"mdc--b7uv6o-key":756,"mdc-eljb4d-key":764,"mdc--szaw4e-key":772,"mdc--8t7ipm-key":787,"mdc--37et2f-key":839,"mdc-kp35yj-key":869,"mdc-3493vb-key":911,"mdc-eugwmi-key":949,"mdc--7ml0ct-key":974,"mdc--f5iefl-key":1233,"mdc--zlmhw-key":1262,"mdc-5ygk3g-key":1278,"mdc-qd4kup-key":1310,"mdc--x9sngs-key":1357,"mdc-dndr8f-key":1373,"mdc-vl66wl-key":1391},{"content":4,"quizQuestionContent":74,"type":93,"pageMeta":94},[5,9,12,16,19,23,26,30,34,37,41,44,48,51,55,58,62,65,68,71],{"id":6,"value":7,"isTypeH1":8},"1884","Обновление DOM при индексах в качестве ключей",true,{"id":10,"value":11,"isTypeParagraph":8},"9896","Для понимания результата необходимо знать, как React сравнивает предыдущий и следующий рендер (reconciliation) и как используется `key` в списках. React сопоставляет элементы списка между рендерами по `key`; если `key` совпал, React считает, что это “тот же” элемент и пытается обновить его содержимое, а не создавать новый узел.",{"id":13,"value":14,"anchor":15,"isTypeH2":8},"4299","Алгоритм согласования и виртуальный DOM","reconciliation-algorithm-and-virtual-dom",{"id":17,"value":18,"isTypeParagraph":8},"9897","При `setState`/`setList` React строит новое дерево элементов (виртуальное представление), сравнивает его с предыдущим и применяет минимальные изменения к реальному DOM. Минимальность достигается тем, что React старается:\n- Переиспользовать существующие DOM-узлы, если считает, что это те же элементы.\n- Обновлять только то, что реально изменилось (например, текстовый узел).",{"id":20,"value":21,"anchor":22,"isTypeH3":8},"4312","Роль атрибута key в списках","role-of-the-key-attribute-in-lists",{"id":24,"value":25,"isTypeParagraph":8},"9898","`key` — это идентификатор элемента списка *между* рендерами. Корректный `key` должен быть:\n- Стабильным (не меняться от рендера к рендеру для одного и того же “логического” элемента).\n- Уникальным среди соседей в списке.",{"id":27,"description":28,"titleAlert":29,"isTypeAlertWarning":8},"672","Индекс массива (`key={id}` где `id` — индекс) подходит только для статических списков без перестановок/вставок/удалений. При изменении порядка это приводит к тому, что React “путает” элементы: DOM-узлы остаются на местах, а данные внутри них меняются.",null,{"id":31,"value":32,"anchor":33,"isTypeH2":8},"4300","Детальный разбор процесса","detailed-analysis-of-the-process",{"id":35,"value":36,"isTypeParagraph":8},"9899","Компонент вызывается так:\n\n```\n\u003CSimpleList list={null} />\n```\n\nЗначит начальное состояние берётся из значения по умолчанию:\n\n```\nconst [list, setList] = useState(props.list || ['a', 'b']);\n```\n\nПоскольку `props.list` равен `null`, выражение `props.list || ['a','b']` даёт `['a','b']`. Первый рендер создаёт элементы:\n\n```\n\u003Cdiv key={0}>a\u003C/div>\n\u003Cdiv key={1}>b\u003C/div>\n```\n\nДалее нажимается кнопка `rotate`:\n\n```\nconst rotateList = () => {\n  setList([...list.reverse()]);\n};\n```\n\nКлючевое здесь:\n1) `reverse()` **мутирует** исходный массив, то есть меняет порядок элементов *внутри того же объекта массива*.  \n2) `[...list.reverse()]` создаёт новый массив, но уже из перевёрнутого исходного. Итоговое новое состояние по значениям: `['b','a']`.\n\nСледующий рендер вернёт:\n\n```\n\u003Cdiv key={0}>b\u003C/div>\n\u003Cdiv key={1}>a\u003C/div>\n```\n\nТеперь важно, как React сопоставит “старое” и “новое”:\n- Элемент с `key={0}` был и остался, значит DOM-узел для первого `div` переиспользуется, а меняется только текст: `a → b`.\n- Элемент с `key={1}` был и остался, значит DOM-узел для второго `div` переиспользуется, а меняется только текст: `b → a`.\n\nТо есть **физического переставления** двух `div` местами в DOM не происходит, потому что с точки зрения ключей порядок не “переехал”: ключ `0` как был в первой позиции, так и остался в первой позиции, и аналогично ключ `1`.\n",{"id":38,"value":39,"anchor":40,"isTypeH3":8},"4313","Почему не вариант 2","why-not-option-2",{"id":42,"value":43,"isTypeParagraph":8},"9900","Полное удаление и создание новых `div` обычно происходит, когда React не может сопоставить элементы (например, ключи изменились или отсутствуют, и структура/типы элементов не совпадают). Здесь ключи совпадают (`0` и `1`), поэтому выгоднее обновить текст внутри существующих узлов.",{"id":45,"value":46,"anchor":47,"isTypeH3":8},"4314","Почему не вариант 3","why-not-option-3",{"id":49,"value":50,"isTypeParagraph":8},"9901","Виртуальный DOM не означает “реальный DOM не меняется”. Наоборот: виртуальное сравнение нужно, чтобы *правильно и эффективно* обновить реальный DOM. Здесь данные изменились, значит изменения попадут и в реальный DOM.",{"id":52,"value":53,"anchor":54,"isTypeH3":8},"4315","Почему не вариант 4","why-not-option-4",{"id":56,"value":57,"isTypeParagraph":8},"9902","Чтобы React “физически” переставил DOM-узлы, нужно, чтобы идентичности элементов были привязаны к данным (например, `key=\"a\"` и `key=\"b\"`), а не к позициям. При `key={index}` идентичность привязана к месту, поэтому React обновляет содержимое, а не меняет порядок узлов.",{"id":59,"value":60,"anchor":61,"isTypeH2":8},"4301","Как сделать корректную “ротацию” визуально","how-to-make-rotation-correct-visually",{"id":63,"value":64,"isTypeParagraph":8},"9903","Если элементы списка имеют уникальные значения, ключ можно привязать к значению:\n\n```\n{list.map((txt) => (\n  \u003Cdiv key={txt}>{txt}\u003C/div>\n))}\n```\n\nТогда при переходе `['a','b'] → ['b','a']` React будет видеть, что элемент с ключом `b` должен оказаться первым, а элемент с ключом `a` — вторым, и сможет корректно отразить перестановку (в терминах reconciliation это будет переупорядочивание по ключам).",{"id":66,"description":67,"titleAlert":29,"isTypeAlertInfo":8},"616","Отдельно следует помнить, что `reverse()` мутирует массив. Для предсказуемости состояния обычно следует избегать мутаций и делать немутирующие преобразования.",{"id":69,"value":70,"isTypeParagraph":8},"9904","Например, без мутации:\n\n```\nconst rotateList = () => {\n  setList(prev => [...prev].reverse());\n};\n```",{"id":72,"value":73,"isTypeParagraph":8},"9905","При `key={index}` React считает элементы с одинаковыми индексами “теми же” элементами между рендерами, поэтому после `reverse()` два `div` в DOM остаются на своих местах, а меняются только их текстовые узлы: первый становится `'b'`, второй — `'a'`.",{"id":75,"options":76,"hint":90,"solution":91,"description":92},"1126",[77,80,84,87],{"id":78,"label":79,"isCorrect":8},"4631","В реальном DOM изменятся только текстовые узлы внутри двух div-элементов. Текст в первом div (который был 'a') станет 'b', а во втором div (который был 'b') станет 'a'. Структура DOM, атрибуты и порядок элементов останутся прежними.",{"id":81,"label":82,"isCorrect":83},"4632","React полностью удалит оба div-элемента из DOM и создаст два новых div-элемента с текстом 'b' и 'a' соответственно, так как изменился порядок элементов в массиве.",false,{"id":85,"label":86,"isCorrect":83},"4633","В реальном DOM ничего не изменится, потому что React использует виртуальный DOM и не станет обновлять реальный DOM из-за такого небольшого изменения.",{"id":88,"label":89,"isCorrect":83},"4634","React поменяет местами два div-элемента в реальном DOM, физически изменив их порядок в дереве, но их внутренний текст останется прежним ('a' и 'b').","Для подобных вопросов следует мысленно ответить на два пункта:\n1) Какие `key` получатся у элементов *до* и *после* обновления?\n2) Привязаны ли ключи к данным (стабильная идентичность) или к позиции (индекс)?\n\nЕсли ключ — индекс, а порядок данных меняется, чаще всего в DOM меняется содержимое узлов, а не их порядок.","**Правильный ответ: 1** - в реальном DOM изменятся только текстовые узлы внутри двух div-элементов. Текст в первом div (который был 'a') станет 'b', а во втором div (который был 'b') станет 'a'. Структура DOM, атрибуты и порядок элементов останутся прежними.","Что произойдет в реальном DOM после нажатия на кнопку \"rotate\" в данном React-компоненте?\n\n```\nimport React, { useState } from 'react';\n\nfunction SimpleList(props) {\n  const [list, setList] = useState(props.list || ['a', 'b']);\n  const rotateList = () => {\n    setList([...list.reverse()]);\n  };\n\n  return (\n    \u003Cdiv>\n      {list.map((txt, id) => (\n        \u003Cdiv key={id}>{txt}\u003C/div>\n      ))}\n      \u003Cbutton onClick={rotateList}>rotate\u003C/button>\n    \u003C/div>\n  );\n}\n```\n\nКомпонент будет вызываться так: \n\n```\n\u003CSimpleList list={null} />\n```","quizQuestion",{"title":95,"description":96,"ogTitle":7,"ogDescription":96,"ogImageUrl":97,"canonical":29,"ogLocale":98,"ogSiteName":99,"ogImageType":100,"ogImageWidth":101,"ogImageHeight":102,"ogType":103,"ogUrl":29},"Как обновится DOM при реверсе списка с ключами-индексами?","Разбор согласования в React и того, что реально меняется в DOM при `reverse()` и `key={index}`.","/og-image.png","ru_RU","goodwebjob.ru","image_jpeg","1200","630","article",{"siteName":105,"siteUrl":106},"GOOD WEB JOB!","https://goodwebjob.ru",{"slugs":108},[109,112,115,118,121,124,127,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],{"name":110,"value":111},"Теоретические задания","theoretical-tasks",{"name":113,"value":114},"Что вернёт этот код: typeof (function(){})()","what-this-code-will-return-typeof-function",{"name":116,"value":117},"С чего начать?","where-to-begin",{"name":119,"value":120},"Почему опасно писать прямо в прототипы базовых типов?","why-is-it-dangerous-to-write-directly-to-the-prototypes-of-basic-types",{"name":122,"value":123},"Backend","backend",{"name":125,"value":126},"Frontend","frontend",{"name":128,"value":129},"Какие логические значения в console.log будут получены?","prototype-what-logical-values-will-be-received-in-console-log",{"name":131,"value":132},"Нечётные числа должны отсортироваться по возрастанию, а чётные должны остаться на своих местах","odd-numbers-should-be-sorted-in-ascending-order-and-even-numbers-should-remain-in-their-original-positions",{"name":134,"value":135}," Найти в массиве неповторяющиеся числа","find-non-repeating-numbers-in-an-array",{"name":137,"value":138},"arr.push(0) повлияет на массив так же, как если бы мы выполнили...","arr-push-0-will-affect-the-array-in-the-same-way-as-if-we-performed",{"name":140,"value":141},"Дана строка: '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":143,"value":144},"Реализовать функцию, похоже как в Jquery","implement-a-function-similar-to-jquery",{"name":146,"value":147},"Для каждого вложенного объекта нужно добавить свойство level, которое равняется числу - номер вложенности","for-each-nested-object-you-need-to-add-the-level-property-which-is-equal-to-a-number-the-nesting-number",{"name":149,"value":150},"Какое значение выведет консоль с object.property?","what-value-will-the-console-output-with-object-property",{"name":152,"value":153},"Что выведется в console.log([arr[0](), arr[0]()])?","what-will-be-displayed-in-console-log-arr-0-arr-0",{"name":155,"value":156},"Вернуть массив от 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":158,"value":159},"Необходимо проверить, являются ли две строки анаграммами друг друга","checks-whether-two-strings-are-anagrams-of-each-other",{"name":161,"value":162},"Определить, является ли слово палиндромом","determines-whether-a-word-is-a-palindrome",{"name":164,"value":165},"Есть массив, в котором лежат объекты с датами, необходимо отсортировать даты по возрастанию","there-is-an-array-containing-objects-with-dates-that-need-to-be-sorted-by-date",{"name":167,"value":168},"Реализовать функцию, принимающую аргументы \"*\", \"1\", \"b\", \"1c\" и возвращающую строку \"1*b*1c\"","implement-a-function-that-accepts-arguments-1-b-1c-and-the-return-string-1-b-1c",{"name":170,"value":171},"Дано дерево (вложенный объект), надо найти сумму всех вершин","given-a-tree-nested-object-it-is-necessary-to-find-the-sum-of-all-vertices",{"name":173,"value":174},"Для каждой ветви дерева записать номер вложенности данной ветви","for-each-branch-of-the-tree-write-down-the-nesting-number-of-this-branch",{"name":176,"value":177},"Есть слова в массиве, необходимо определить, состоят ли они из одних и тех же букв","there-are-words-in-the-array-it-is-necessary-to-determine-whether-they-consist-of-the-same-letters",{"name":179,"value":180},"Числа от 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":182,"value":183},"Есть строка, состоящая из разных скобок, необходимо проверить, закрыты ли все","there-is-a-string-consisting-of-different-brackets-it-is-necessary-to-check-whether-all-are-closed",{"name":185,"value":186},"Напишите функцию, который сделает из массива объект","write-a-function-that-will-make-an-object-out-of-an-array",{"name":188,"value":189},"Что выведет console.log в результате выполнения цикла while?","what-will-console-log-output-as-a-result-of-executing-the-while-loop",{"name":191,"value":192},"Есть функция и объект. Напишите все известные вам способы, чтобы вывести в консоли значение 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":194,"value":195},"Что выведет консоль в случае присвоения свойства массиву по строковому отрицательному индексу?","what-will-the-console-display-if-a-property-is-assigned-to-an-array-using-a-negative-string-index",{"name":197,"value":198},"Что выведет консоль в случае удаления элемента массива с помощью оператора delete?","what-will-the-console-output-if-an-array-element-is-deleted-using-the-delete-operator",{"name":200,"value":201},"Уникализация значений в массиве","unifying-values-in-an-array",{"name":203,"value":204},"«Расплющивание» массива","flattening-the-array",{"name":206,"value":207},"Что вернёт метод book.getUpperName()?","what-will-the-book-get-upper-name-method-return",{"name":209,"value":210},"Сжатие строк","string-compression",{"name":212,"value":213},"Что выведет консоль в случае присвоения свойства массиву по строковому положительному индексу?","what-will-the-console-display-if-a-property-is-assigned-to-an-array-using-a-positive-string-index",{"name":215,"value":216},"Что получится в результате передачи объекта как аргумента в функцию и выполнения кода?","what-will-happen-when-an-object-is-passed-as-an-argument-to-a-function-and-the-code-is-executed",{"name":218,"value":219},"Как браузер после ввода домена понимает, откуда брать сайт?","how-does-the-browser-know-where-to-get-the-website-after-entering-the-domain",{"name":221,"value":222},"Как домен попадает в DNS в таблицу соответствия: домен – ip","how-does-a-domain-get-into-the-dns-mapping-table-domain-ip",{"name":224,"value":225},"Как браузер решает, какое соединение ему открывать, TCP или UDP?","how-does-a-browser-decide-whether-to-open-a-tcp-or-udp-connection",{"name":227,"value":228},"Ключевые отличия TCP и UDP","key-differences-between-tcp-and-udp",{"name":230,"value":231},"\"TCP/IP\" - кем является TCP, а кем IP в данном случае?","tcp-ip-who-is-tcp-and-who-is-ip-in-this-case",{"name":233,"value":234},"Что такое HTTP и из чего состоит?","what-is-http-and-what-does-it-consist-of",{"name":236,"value":237},"Что такое заголовки в HTTP и зачем они нужны?","what-are-http-headers-and-why-do-we-need-them",{"name":239,"value":240},"Что такое параметры в HTTP?","what-are-http-parameters",{"name":242,"value":243},"Где находится HTML-код в структуре HTTP-ответа?","where-is-the-html-code-located-in-the-http-response-structure",{"name":245,"value":246},"Что такое HTML?","what-is-html",{"name":248,"value":249},"Чем отличаются 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":251,"value":252},"Пользователь авторизован на сайте. Как сервер узнает об этом с последующими другими заходами, что «я – авторизованный пользователь»?","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":254,"value":255},"Что такое cookie?","what-is-a-cookie",{"name":257,"value":258},"Кто является инициатором записи cookie в браузере?","who-initiates-the-cookie-recording-in-the-browser",{"name":260,"value":261},"Есть ли возможность с клиента (с браузера) управлять cookie?","is-it-possible-to-manage-cookies-from-the-client-browser",{"name":263,"value":264},"Лайвкодинг","livecoding",{"name":266,"value":267},"Что вернёт следующий код? Object.create(null).hasOwnProperty('toString')","what-will-the-following-code-return-object-create-null-has-own-property-to-string",{"name":269,"value":270},"Всё, что идет по HTTPS – оно защищено?","is-everything-that-goes-through-https-secure",{"name":272,"value":273},"Все данные зашифрованы, используется 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":275,"value":276},"Есть веб-приложение. Помимо 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":278,"value":279},"Как браузер парсит JavaScript и изображения при рендеринге?","how-the-browser-parses-javascript-and-images-when-rendering",{"name":281,"value":282},"Что происходит, когда HTTP прислал HTML? Что браузер дальше делает c HTML с учетом того, что она валидная?","what-happens-when-http-sends-html-what-does-the-browser-do-with-this-html-given-that-it-is-valid",{"name":284,"value":285},"Что в браузере блокирует рендеринг страницы?","what-is-blocking-the-page-rendering-in-the-browser",{"name":287,"value":288},"Что такое DOM в браузере? Что такое CSSOM?","what-is-dom-in-a-browser-what-is-cssom",{"name":290,"value":291},"Что является узлами в DOM?","what-are-nodes-in-the-dom",{"name":293,"value":294},"Из чего состоит CSSOM?","what-does-cssom-consist-of",{"name":296,"value":297},"Дан HTML-код. Какой будет цвет у текста «Some dummy text»?","the-html-code-is-given-what-will-be-the-color-of-the-some-dummy-text",{"name":299,"value":300},"Есть шаблон HTML и CSS кода. Какой будет цвет у текста «Таким образом, постоянное»?","there-is-a-template-for-html-and-css-code-what-color-will-the-text-thus-constant-have",{"name":302,"value":303},"Есть шаблон вложенного 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":305,"value":306},"Есть шаблон вложенного HTML кода. Будет ли display:block у body влиять на span?","there-is-a-template-for-embedded-html-code-will-there-be-a-display-does-bodys-block-affect-span",{"name":308,"value":309},"Есть HTML код. Будет ли font-weight на span влиять?","there-is-an-html-code-will-font-weight-affect-span",{"name":311,"value":312},"Flexbox и Grid, чем отличаются друг от друга?","what-are-the-differences-between-flexbox-and-grid",{"name":314,"value":315},"Заменяют ли Flexbox и Grid друг друга?","do-flexbox-and-grid-replace-each-other",{"name":317,"value":318},"Есть CSS и JS анимация. Какая между ними разница, что быстрее, что более удобно?","there-are-css-and-js-animations-what-is-the-difference-between-them-and-which-is-faster-and-more-convenient",{"name":320,"value":321},"Сборник задач","tasks",{"name":323,"value":324},"Какие способы объявления функции есть в JavaScript?","what-are-the-ways-to-declare-a-function-in-javascript",{"name":326,"value":327},"Что такое this в JavaScript?","what-is-this-in-javascript",{"name":329,"value":330},"Что такое Event Loop, как работает?","what-is-an-event-loop-and-how-does-it-work",{"name":332,"value":333},"Что будет, если вызвать typeof на необъявленной переменной?","what-happens-if-you-call-typeof-on-an-undeclared-variable",{"name":335,"value":336},"Что показывает оператор typeof в JavaScript?","what-does-the-typeof-operator-show-in-javascript",{"name":338,"value":339},"Какие типы данных существует в JavaScript?","what-types-of-data-exist-in-javascript",{"name":341,"value":342},"Какую структуру использовать для хранения упорядоченного списка строк в JavaScript?","what-is-the-best-structure-to-use-for-storing-an-ordered-list-of-strings-in-javascript",{"name":344,"value":345},"Что вернет typeof для массива?","what-will-typeof-return-for-an-array",{"name":347,"value":348},"Почему оператор typeof, применённый к массиву, возвращает объект?","why-does-the-typeof-operator-applied-to-an-array-return-an-object",{"name":350,"value":351},"Если нужно хранить список уникальных строк, какую структуру данных выбрать?","if-you-need-to-store-a-list-of-unique-strings-which-data-structure-should-i-choose",{"name":353,"value":354},"Что возвращает typeof для new Set в JavaScript?","what-does-typeof-return-for-new-set-in-javascript",{"name":356,"value":357},"Для чего нужен React, какие он решает проблемы?","what-is-react-used-for-and-what-problems-does-it-solve",{"name":359,"value":360},"Если убрать в React VDOM/Fiber, и вручную изменять DOM, разве это не оптимально?","if-you-remove-the-vdom-fiber-in-react-and-manually-change-the-dom-isn-t-that-optimal",{"name":362,"value":363},"Есть блок кода. Что в реальном DOM изменится после нажатия на кнопку?","there-is-a-block-of-code-what-changes-in-the-real-dom-after-clicking-the-button",{"name":365,"value":366},"Есть код, в котором список и кнопка. Что в реальном 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":368,"value":369},"Зачем нужен Redux (Mobx/Effector)? Зачем нужен менеджер состояния? Какие проблемы решает?","why-do-we-need-redux-mobx-effector-why-do-we-need-a-state-manager-what-problems-does-it-solve",{"name":371,"value":372},"Как диагностировать и исправить нежелательное изменение цвета фона по клику на кнопку, если исходный код сайта запутан и недоступен для прямого чтения?","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":374,"value":375},"Разрабатывал, взял закоммитил, запушил. Оказалось, что запушил не в ту ветку, точнее, коммит не в ту ветку. Какие действия?","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":377,"value":378},"В git есть несколько вариантов слияния веток, какие? Чем отличаются?","git-has-several-options-for-merging-branches-which-ones-how-are-they-different",{"name":380,"value":381},"Какие существуют стратегии ветвления для работы команды? Что это такое?","what-are-the-branching-strategies-for-the-team-what-is-it",{"name":383,"value":384},"По каким характеристикам, ревьюер понимает, что данный код - хороший, а этот код - плохой?","how-does-a-reviewer-know-which-code-is-good-and-which-code-is-bad",{"name":386,"value":387},"Дан фрагмент bash-скрипта: cd ~; mkdir foo... Что в нем происходит?","here-is-a-fragment-of-a-bash-script-cd-mkdir-foo-what-is-happening-in-this-script",{"name":389,"value":390},"Дан фрагмент 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":392,"value":393},"Что такое алгоритмическая сложность?","what-is-algorithmic-complexity",{"name":395,"value":396},"Какая алгоритмическая сложность у \"быстрой сортировки\"?","what-is-the-algorithmic-complexity-of-quick-sort",{"name":398,"value":399},"Почему в JavaScript два объекта с одинаковым содержимым при сравнении возвращают false?","why-do-two-objects-with-the-same-content-return-false-when-compared-in-javascript",{"name":401,"value":402},"Каким способом может выполняться авторизация пользователя на сайте?","how-can-a-user-be-authorized-on-a-website",{"name":404,"value":405},"В чем разница между микро- и макро-тасками в JavaScript?","what-is-the-difference-between-micro-and-macro-tasks-in-javascript",{"name":407,"value":408},"В комнате три человека. Какова вероятность того, что хотя бы двое из них одного пола? То есть два и более.","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":410,"value":411},"Есть монета. Ее подбрасывают пять раз подряд. Каждый раз записывается, что выпало - орел или решка. Сколько разных последовательностей орлов и решек может при этом получиться?","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":413,"value":414},"Как гарантированно найти лёгкую фальшивую монету среди 8 за минимальное число взвешиваний на чашечных весах?","how-can-you-guarantee-to-find-an-easy-fake-coin-among-8-in-the-minimum-number-of-weighings-on-a-balance-scale",{"name":416,"value":417},"Подготовка к тех.интервью","technical-interview",{"name":419,"value":420},"Верно ли утверждение, что злоумышленник, контролирующий роутер и прослушивающий трафик, может получить логины и пароли от сайтов, на которые заходит клиент?","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":422,"value":423},"Что такое DNS, как DNS находит нужный IP-адрес?","what-is-dns-and-how-does-dns-find-the-correct-ip-address",{"name":425,"value":426},"Переменные объявлены следующим образом: a=3; b=«hello»;. Укажите правильное утверждение","variables-are-declared-as-follows-specify-the-correct-statement",{"name":428,"value":429},"Какой механизм лежит в основе оптимизации обновлений DOM в React?","what-is-the-underlying-mechanism-for-optimizing-dom-updates-in-react",{"name":431,"value":432},"Что мешает организовать централизованное состояние без менеджера состояния? Если организовать состояние механизмами реакта: контекстом, стейтом, в чем проблема? Что менеджеры состояния привносят?","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",[434],{"label":416,"slug":417,"to":435},"/technical-interview/where-to-begin",{"navigationList":437,"navigationSublist":443},[438,440],{"path":435,"isActive":83,"name":116,"icon":439,"isNavbarMobileDisabled":8},"material-symbols:visibility-outline-rounded",{"path":441,"isActive":8,"name":320,"icon":442,"isNavbarMobileDisabled":83},"/technical-interview/tasks","material-symbols:task-outline",[444,451,470,479,484,579,596,603,608,651,666,671],{"title":445,"list":446,"isOpened":83},"Bash",[447,449],{"name":386,"path":448,"isActive":83},"/technical-interview/tasks/here-is-a-fragment-of-a-bash-script-cd-mkdir-foo-what-is-happening-in-this-script",{"name":389,"path":450,"isActive":83},"/technical-interview/tasks/here-is-a-fragment-of-a-bash-script-target-ps-af-grep-1-head-n-1",{"title":452,"list":453,"isOpened":83},"CSS",[454,456,458,460,462,464,466,468],{"name":296,"path":455,"isActive":83},"/technical-interview/tasks/the-html-code-is-given-what-will-be-the-color-of-the-some-dummy-text",{"name":299,"path":457,"isActive":83},"/technical-interview/tasks/there-is-a-template-for-html-and-css-code-what-color-will-the-text-thus-constant-have",{"name":302,"path":459,"isActive":83},"/technical-interview/tasks/there-is-a-template-for-embedded-html-code-what-will-be-the-color-of-the-one-more-dummy-text",{"name":305,"path":461,"isActive":83},"/technical-interview/tasks/there-is-a-template-for-embedded-html-code-will-there-be-a-display-does-bodys-block-affect-span",{"name":308,"path":463,"isActive":83},"/technical-interview/tasks/there-is-an-html-code-will-font-weight-affect-span",{"name":311,"path":465,"isActive":83},"/technical-interview/tasks/what-are-the-differences-between-flexbox-and-grid",{"name":314,"path":467,"isActive":83},"/technical-interview/tasks/do-flexbox-and-grid-replace-each-other",{"name":317,"path":469,"isActive":83},"/technical-interview/tasks/there-are-css-and-js-animations-what-is-the-difference-between-them-and-which-is-faster-and-more-convenient",{"title":471,"list":472,"isOpened":83},"Git",[473,475,477],{"name":374,"path":474,"isActive":83},"/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":377,"path":476,"isActive":83},"/technical-interview/tasks/git-has-several-options-for-merging-branches-which-ones-how-are-they-different",{"name":380,"path":478,"isActive":83},"/technical-interview/tasks/what-are-the-branching-strategies-for-the-team-what-is-it",{"title":480,"list":481,"isOpened":83},"HTML",[482],{"name":245,"path":483,"isActive":83},"/technical-interview/tasks/what-is-html",{"title":485,"list":486,"isOpened":83},"JavaScript",[487,489,491,493,495,497,499,501,503,505,507,509,511,513,515,517,519,521,523,525,527,529,531,533,535,537,539,541,543,545,547,549,551,553,555,557,559,561,563,565,567,569,571,573,575,577],{"name":128,"path":488,"isActive":83},"/technical-interview/tasks/prototype-what-logical-values-will-be-received-in-console-log",{"name":119,"path":490,"isActive":83},"/technical-interview/tasks/why-is-it-dangerous-to-write-directly-to-the-prototypes-of-basic-types",{"name":266,"path":492,"isActive":83},"/technical-interview/tasks/what-will-the-following-code-return-object-create-null-has-own-property-to-string",{"name":149,"path":494,"isActive":83},"/technical-interview/tasks/what-value-will-the-console-output-with-object-property",{"name":152,"path":496,"isActive":83},"/technical-interview/tasks/what-will-be-displayed-in-console-log-arr-0-arr-0",{"name":188,"path":498,"isActive":83},"/technical-interview/tasks/what-will-console-log-output-as-a-result-of-executing-the-while-loop",{"name":191,"path":500,"isActive":83},"/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":206,"path":502,"isActive":83},"/technical-interview/tasks/what-will-the-book-get-upper-name-method-return",{"name":425,"path":504,"isActive":83},"/technical-interview/tasks/variables-are-declared-as-follows-specify-the-correct-statement",{"name":212,"path":506,"isActive":83},"/technical-interview/tasks/what-will-the-console-display-if-a-property-is-assigned-to-an-array-using-a-positive-string-index",{"name":194,"path":508,"isActive":83},"/technical-interview/tasks/what-will-the-console-display-if-a-property-is-assigned-to-an-array-using-a-negative-string-index",{"name":197,"path":510,"isActive":83},"/technical-interview/tasks/what-will-the-console-output-if-an-array-element-is-deleted-using-the-delete-operator",{"name":113,"path":512,"isActive":83},"/technical-interview/tasks/what-this-code-will-return-typeof-function",{"name":215,"path":514,"isActive":83},"/technical-interview/tasks/what-will-happen-when-an-object-is-passed-as-an-argument-to-a-function-and-the-code-is-executed",{"name":323,"path":516,"isActive":83},"/technical-interview/tasks/what-are-the-ways-to-declare-a-function-in-javascript",{"name":326,"path":518,"isActive":83},"/technical-interview/tasks/what-is-this-in-javascript",{"name":329,"path":520,"isActive":83},"/technical-interview/tasks/what-is-an-event-loop-and-how-does-it-work",{"name":332,"path":522,"isActive":83},"/technical-interview/tasks/what-happens-if-you-call-typeof-on-an-undeclared-variable",{"name":335,"path":524,"isActive":83},"/technical-interview/tasks/what-does-the-typeof-operator-show-in-javascript",{"name":338,"path":526,"isActive":83},"/technical-interview/tasks/what-types-of-data-exist-in-javascript",{"name":341,"path":528,"isActive":83},"/technical-interview/tasks/what-is-the-best-structure-to-use-for-storing-an-ordered-list-of-strings-in-javascript",{"name":344,"path":530,"isActive":83},"/technical-interview/tasks/what-will-typeof-return-for-an-array",{"name":347,"path":532,"isActive":83},"/technical-interview/tasks/why-does-the-typeof-operator-applied-to-an-array-return-an-object",{"name":350,"path":534,"isActive":83},"/technical-interview/tasks/if-you-need-to-store-a-list-of-unique-strings-which-data-structure-should-i-choose",{"name":353,"path":536,"isActive":83},"/technical-interview/tasks/what-does-typeof-return-for-new-set-in-javascript",{"name":398,"path":538,"isActive":83},"/technical-interview/tasks/why-do-two-objects-with-the-same-content-return-false-when-compared-in-javascript",{"name":404,"path":540,"isActive":83},"/technical-interview/tasks/what-is-the-difference-between-micro-and-macro-tasks-in-javascript",{"name":137,"path":542,"isActive":83},"/technical-interview/tasks/arr-push-0-will-affect-the-array-in-the-same-way-as-if-we-performed",{"name":155,"path":544,"isActive":83},"/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":140,"path":546,"isActive":83},"/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":170,"path":548,"isActive":83},"/technical-interview/tasks/given-a-tree-nested-object-it-is-necessary-to-find-the-sum-of-all-vertices",{"name":146,"path":550,"isActive":83},"/technical-interview/tasks/for-each-nested-object-you-need-to-add-the-level-property-which-is-equal-to-a-number-the-nesting-number",{"name":173,"path":552,"isActive":83},"/technical-interview/tasks/for-each-branch-of-the-tree-write-down-the-nesting-number-of-this-branch",{"name":164,"path":554,"isActive":83},"/technical-interview/tasks/there-is-an-array-containing-objects-with-dates-that-need-to-be-sorted-by-date",{"name":176,"path":556,"isActive":83},"/technical-interview/tasks/there-are-words-in-the-array-it-is-necessary-to-determine-whether-they-consist-of-the-same-letters",{"name":182,"path":558,"isActive":83},"/technical-interview/tasks/there-is-a-string-consisting-of-different-brackets-it-is-necessary-to-check-whether-all-are-closed",{"name":134,"path":560,"isActive":83},"/technical-interview/tasks/find-non-repeating-numbers-in-an-array",{"name":185,"path":562,"isActive":83},"/technical-interview/tasks/write-a-function-that-will-make-an-object-out-of-an-array",{"name":158,"path":564,"isActive":83},"/technical-interview/tasks/checks-whether-two-strings-are-anagrams-of-each-other",{"name":131,"path":566,"isActive":83},"/technical-interview/tasks/odd-numbers-should-be-sorted-in-ascending-order-and-even-numbers-should-remain-in-their-original-positions",{"name":161,"path":568,"isActive":83},"/technical-interview/tasks/determines-whether-a-word-is-a-palindrome",{"name":203,"path":570,"isActive":83},"/technical-interview/tasks/flattening-the-array",{"name":167,"path":572,"isActive":83},"/technical-interview/tasks/implement-a-function-that-accepts-arguments-1-b-1c-and-the-return-string-1-b-1c",{"name":209,"path":574,"isActive":83},"/technical-interview/tasks/string-compression",{"name":200,"path":576,"isActive":83},"/technical-interview/tasks/unifying-values-in-an-array",{"name":179,"path":578,"isActive":83},"/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":580,"list":581,"isOpened":83},"React",[582,584,586,588,590,592,594],{"name":356,"path":583,"isActive":83},"/technical-interview/tasks/what-is-react-used-for-and-what-problems-does-it-solve",{"name":428,"path":585,"isActive":83},"/technical-interview/tasks/what-is-the-underlying-mechanism-for-optimizing-dom-updates-in-react",{"name":359,"path":587,"isActive":83},"/technical-interview/tasks/if-you-remove-the-vdom-fiber-in-react-and-manually-change-the-dom-isn-t-that-optimal",{"name":362,"path":589,"isActive":83},"/technical-interview/tasks/there-is-a-block-of-code-what-changes-in-the-real-dom-after-clicking-the-button",{"name":365,"path":591,"isActive":83},"/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":368,"path":593,"isActive":83},"/technical-interview/tasks/why-do-we-need-redux-mobx-effector-why-do-we-need-a-state-manager-what-problems-does-it-solve",{"name":431,"path":595,"isActive":83},"/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":597,"list":598,"isOpened":83},"Алгоритмы",[599,601],{"name":392,"path":600,"isActive":83},"/technical-interview/tasks/what-is-algorithmic-complexity",{"name":395,"path":602,"isActive":83},"/technical-interview/tasks/what-is-the-algorithmic-complexity-of-quick-sort",{"title":604,"list":605,"isOpened":83},"Дебаггинг",[606],{"name":371,"path":607,"isActive":83},"/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":609,"list":610,"isOpened":83},"Компьютерные сети",[611,613,615,617,619,621,623,625,627,629,631,633,635,637,639,641,643,645,647,649],{"name":218,"path":612,"isActive":83},"/technical-interview/tasks/how-does-the-browser-know-where-to-get-the-website-after-entering-the-domain",{"name":422,"path":614,"isActive":83},"/technical-interview/tasks/what-is-dns-and-how-does-dns-find-the-correct-ip-address",{"name":221,"path":616,"isActive":83},"/technical-interview/tasks/how-does-a-domain-get-into-the-dns-mapping-table-domain-ip",{"name":224,"path":618,"isActive":83},"/technical-interview/tasks/how-does-a-browser-decide-whether-to-open-a-tcp-or-udp-connection",{"name":227,"path":620,"isActive":83},"/technical-interview/tasks/key-differences-between-tcp-and-udp",{"name":230,"path":622,"isActive":83},"/technical-interview/tasks/tcp-ip-who-is-tcp-and-who-is-ip-in-this-case",{"name":233,"path":624,"isActive":83},"/technical-interview/tasks/what-is-http-and-what-does-it-consist-of",{"name":236,"path":626,"isActive":83},"/technical-interview/tasks/what-are-http-headers-and-why-do-we-need-them",{"name":239,"path":628,"isActive":83},"/technical-interview/tasks/what-are-http-parameters",{"name":242,"path":630,"isActive":83},"/technical-interview/tasks/where-is-the-html-code-located-in-the-http-response-structure",{"name":248,"path":632,"isActive":83},"/technical-interview/tasks/what-are-the-differences-between-http-versions-1-0-1-1-2-0-and-3-0",{"name":251,"path":634,"isActive":83},"/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":254,"path":636,"isActive":83},"/technical-interview/tasks/what-is-a-cookie",{"name":257,"path":638,"isActive":83},"/technical-interview/tasks/who-initiates-the-cookie-recording-in-the-browser",{"name":260,"path":640,"isActive":83},"/technical-interview/tasks/is-it-possible-to-manage-cookies-from-the-client-browser",{"name":419,"path":642,"isActive":83},"/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":269,"path":644,"isActive":83},"/technical-interview/tasks/is-everything-that-goes-through-https-secure",{"name":272,"path":646,"isActive":83},"/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":275,"path":648,"isActive":83},"/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":401,"path":650,"isActive":83},"/technical-interview/tasks/how-can-a-user-be-authorized-on-a-website",{"title":652,"list":653,"isOpened":83},"Отрисовка в браузере",[654,656,658,660,662,664],{"name":281,"path":655,"isActive":83},"/technical-interview/tasks/what-happens-when-http-sends-html-what-does-the-browser-do-with-this-html-given-that-it-is-valid",{"name":278,"path":657,"isActive":83},"/technical-interview/tasks/how-the-browser-parses-javascript-and-images-when-rendering",{"name":284,"path":659,"isActive":83},"/technical-interview/tasks/what-is-blocking-the-page-rendering-in-the-browser",{"name":287,"path":661,"isActive":83},"/technical-interview/tasks/what-is-dom-in-a-browser-what-is-cssom",{"name":290,"path":663,"isActive":83},"/technical-interview/tasks/what-are-nodes-in-the-dom",{"name":293,"path":665,"isActive":83},"/technical-interview/tasks/what-does-cssom-consist-of",{"title":667,"list":668,"isOpened":83},"Ревью кода",[669],{"name":383,"path":670,"isActive":83},"/technical-interview/tasks/how-does-a-reviewer-know-which-code-is-good-and-which-code-is-bad",{"title":672,"list":673,"isOpened":83},"Теория вероятности",[674,676,678],{"name":407,"path":675,"isActive":83},"/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":410,"path":677,"isActive":83},"/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":413,"path":679,"isActive":83},"/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":681,"copyright":684,"reportError":685,"socialNetwork":687},{"link":682,"title":683},"https://t.me/baurinanton","Сотрудничество","© “GOOD WEB JOB!”",{"label":686,"link":682},"Сообщить об ошибке",{"label":688,"socialNetworkList":689},"Мы в соцсетях:",[690,693,696],{"icon":29,"link":691,"title":692},"https://max.ru/u/f9LHodD0cOKMaukdnnahTeL5pwvjrPfUaZ4S8_1rsNy9I9qsmc9Ar3kP_y8","Max",{"icon":694,"link":682,"title":695},"ic:baseline-telegram","Telegram",{"icon":697,"link":698,"title":699},"ri:vk-fill","https://vk.com/baurinanton","VK",{"data":701,"body":702},{},{"type":703,"children":704},"root",[705,713,726,731],{"type":706,"tag":707,"props":708,"children":709},"element","p",{},[710],{"type":711,"value":712},"text","Что произойдет в реальном DOM после нажатия на кнопку \"rotate\" в данном React-компоненте?",{"type":706,"tag":714,"props":715,"children":719},"pre",{"className":716,"code":718,"language":711},[717],"language-text","import React, { useState } from 'react';\n\nfunction SimpleList(props) {\n  const [list, setList] = useState(props.list || ['a', 'b']);\n  const rotateList = () => {\n    setList([...list.reverse()]);\n  };\n\n  return (\n    \u003Cdiv>\n      {list.map((txt, id) => (\n        \u003Cdiv key={id}>{txt}\u003C/div>\n      ))}\n      \u003Cbutton onClick={rotateList}>rotate\u003C/button>\n    \u003C/div>\n  );\n}\n",[720],{"type":706,"tag":721,"props":722,"children":724},"code",{"__ignoreMap":723},"",[725],{"type":711,"value":718},{"type":706,"tag":707,"props":727,"children":728},{},[729],{"type":711,"value":730},"Компонент будет вызываться так:",{"type":706,"tag":714,"props":732,"children":735},{"className":733,"code":734,"language":711},[717],"\u003CSimpleList list={null} />\n",[736],{"type":706,"tag":721,"props":737,"children":738},{"__ignoreMap":723},[739],{"type":711,"value":734},{"data":741,"body":742},{},{"type":703,"children":743},[744],{"type":706,"tag":707,"props":745,"children":746},{},[747],{"type":711,"value":79},{"data":749,"body":750},{},{"type":703,"children":751},[752],{"type":706,"tag":707,"props":753,"children":754},{},[755],{"type":711,"value":82},{"data":757,"body":758},{},{"type":703,"children":759},[760],{"type":706,"tag":707,"props":761,"children":762},{},[763],{"type":711,"value":86},{"data":765,"body":766},{},{"type":703,"children":767},[768],{"type":706,"tag":707,"props":769,"children":770},{},[771],{"type":711,"value":89},{"data":773,"body":774},{},{"type":703,"children":775},[776],{"type":706,"tag":707,"props":777,"children":778},{},[779,785],{"type":706,"tag":780,"props":781,"children":782},"strong",{},[783],{"type":711,"value":784},"Правильный ответ: 1",{"type":711,"value":786}," - в реальном DOM изменятся только текстовые узлы внутри двух div-элементов. Текст в первом div (который был 'a') станет 'b', а во втором div (который был 'b') станет 'a'. Структура DOM, атрибуты и порядок элементов останутся прежними.",{"data":788,"body":789},{},{"type":703,"children":790},[791,796,834],{"type":706,"tag":707,"props":792,"children":793},{},[794],{"type":711,"value":795},"Для подобных вопросов следует мысленно ответить на два пункта:",{"type":706,"tag":797,"props":798,"children":799},"ol",{},[800,829],{"type":706,"tag":801,"props":802,"children":803},"li",{},[804,806,812,814,820,822,827],{"type":711,"value":805},"Какие ",{"type":706,"tag":721,"props":807,"children":809},{"className":808},[],[810],{"type":711,"value":811},"key",{"type":711,"value":813}," получатся у элементов ",{"type":706,"tag":815,"props":816,"children":817},"em",{},[818],{"type":711,"value":819},"до",{"type":711,"value":821}," и ",{"type":706,"tag":815,"props":823,"children":824},{},[825],{"type":711,"value":826},"после",{"type":711,"value":828}," обновления?",{"type":706,"tag":801,"props":830,"children":831},{},[832],{"type":711,"value":833},"Привязаны ли ключи к данным (стабильная идентичность) или к позиции (индекс)?",{"type":706,"tag":707,"props":835,"children":836},{},[837],{"type":711,"value":838},"Если ключ — индекс, а порядок данных меняется, чаще всего в DOM меняется содержимое узлов, а не их порядок.",{"data":840,"body":841},{},{"type":703,"children":842},[843],{"type":706,"tag":707,"props":844,"children":845},{},[846,848,853,855,860,862,867],{"type":711,"value":847},"Для понимания результата необходимо знать, как React сравнивает предыдущий и следующий рендер (reconciliation) и как используется ",{"type":706,"tag":721,"props":849,"children":851},{"className":850},[],[852],{"type":711,"value":811},{"type":711,"value":854}," в списках. React сопоставляет элементы списка между рендерами по ",{"type":706,"tag":721,"props":856,"children":858},{"className":857},[],[859],{"type":711,"value":811},{"type":711,"value":861},"; если ",{"type":706,"tag":721,"props":863,"children":865},{"className":864},[],[866],{"type":711,"value":811},{"type":711,"value":868}," совпал, React считает, что это “тот же” элемент и пытается обновить его содержимое, а не создавать новый узел.",{"data":870,"body":871},{},{"type":703,"children":872},[873,897],{"type":706,"tag":707,"props":874,"children":875},{},[876,881,883,888,890,895],{"type":706,"tag":721,"props":877,"children":879},{"className":878},[],[880],{"type":711,"value":811},{"type":711,"value":882}," — это идентификатор элемента списка ",{"type":706,"tag":815,"props":884,"children":885},{},[886],{"type":711,"value":887},"между",{"type":711,"value":889}," рендерами. Корректный ",{"type":706,"tag":721,"props":891,"children":893},{"className":892},[],[894],{"type":711,"value":811},{"type":711,"value":896}," должен быть:",{"type":706,"tag":898,"props":899,"children":900},"ul",{},[901,906],{"type":706,"tag":801,"props":902,"children":903},{},[904],{"type":711,"value":905},"Стабильным (не меняться от рендера к рендеру для одного и того же “логического” элемента).",{"type":706,"tag":801,"props":907,"children":908},{},[909],{"type":711,"value":910},"Уникальным среди соседей в списке.",{"data":912,"body":913},{},{"type":703,"children":914},[915,936],{"type":706,"tag":707,"props":916,"children":917},{},[918,920,926,928,934],{"type":711,"value":919},"При ",{"type":706,"tag":721,"props":921,"children":923},{"className":922},[],[924],{"type":711,"value":925},"setState",{"type":711,"value":927},"/",{"type":706,"tag":721,"props":929,"children":931},{"className":930},[],[932],{"type":711,"value":933},"setList",{"type":711,"value":935}," React строит новое дерево элементов (виртуальное представление), сравнивает его с предыдущим и применяет минимальные изменения к реальному DOM. Минимальность достигается тем, что React старается:",{"type":706,"tag":898,"props":937,"children":938},{},[939,944],{"type":706,"tag":801,"props":940,"children":941},{},[942],{"type":711,"value":943},"Переиспользовать существующие DOM-узлы, если считает, что это те же элементы.",{"type":706,"tag":801,"props":945,"children":946},{},[947],{"type":711,"value":948},"Обновлять только то, что реально изменилось (например, текстовый узел).",{"data":950,"body":951},{},{"type":703,"children":952},[953],{"type":706,"tag":707,"props":954,"children":955},{},[956,958,964,966,972],{"type":711,"value":957},"Индекс массива (",{"type":706,"tag":721,"props":959,"children":961},{"className":960},[],[962],{"type":711,"value":963},"key={id}",{"type":711,"value":965}," где ",{"type":706,"tag":721,"props":967,"children":969},{"className":968},[],[970],{"type":711,"value":971},"id",{"type":711,"value":973}," — индекс) подходит только для статических списков без перестановок/вставок/удалений. При изменении порядка это приводит к тому, что React “путает” элементы: DOM-узлы остаются на местах, а данные внутри них меняются.",{"data":975,"body":976},{},{"type":703,"children":977},[978,983,991,996,1005,1042,1051,1064,1073,1078,1124,1129,1138,1143,1199],{"type":706,"tag":707,"props":979,"children":980},{},[981],{"type":711,"value":982},"Компонент вызывается так:",{"type":706,"tag":714,"props":984,"children":986},{"className":985,"code":734,"language":711},[717],[987],{"type":706,"tag":721,"props":988,"children":989},{"__ignoreMap":723},[990],{"type":711,"value":734},{"type":706,"tag":707,"props":992,"children":993},{},[994],{"type":711,"value":995},"Значит начальное состояние берётся из значения по умолчанию:",{"type":706,"tag":714,"props":997,"children":1000},{"className":998,"code":999,"language":711},[717],"const [list, setList] = useState(props.list || ['a', 'b']);\n",[1001],{"type":706,"tag":721,"props":1002,"children":1003},{"__ignoreMap":723},[1004],{"type":711,"value":999},{"type":706,"tag":707,"props":1006,"children":1007},{},[1008,1010,1016,1018,1024,1026,1032,1034,1040],{"type":711,"value":1009},"Поскольку ",{"type":706,"tag":721,"props":1011,"children":1013},{"className":1012},[],[1014],{"type":711,"value":1015},"props.list",{"type":711,"value":1017}," равен ",{"type":706,"tag":721,"props":1019,"children":1021},{"className":1020},[],[1022],{"type":711,"value":1023},"null",{"type":711,"value":1025},", выражение ",{"type":706,"tag":721,"props":1027,"children":1029},{"className":1028},[],[1030],{"type":711,"value":1031},"props.list || ['a','b']",{"type":711,"value":1033}," даёт ",{"type":706,"tag":721,"props":1035,"children":1037},{"className":1036},[],[1038],{"type":711,"value":1039},"['a','b']",{"type":711,"value":1041},". Первый рендер создаёт элементы:",{"type":706,"tag":714,"props":1043,"children":1046},{"className":1044,"code":1045,"language":711},[717],"\u003Cdiv key={0}>a\u003C/div>\n\u003Cdiv key={1}>b\u003C/div>\n",[1047],{"type":706,"tag":721,"props":1048,"children":1049},{"__ignoreMap":723},[1050],{"type":711,"value":1045},{"type":706,"tag":707,"props":1052,"children":1053},{},[1054,1056,1062],{"type":711,"value":1055},"Далее нажимается кнопка ",{"type":706,"tag":721,"props":1057,"children":1059},{"className":1058},[],[1060],{"type":711,"value":1061},"rotate",{"type":711,"value":1063},":",{"type":706,"tag":714,"props":1065,"children":1068},{"className":1066,"code":1067,"language":711},[717],"const rotateList = () => {\n  setList([...list.reverse()]);\n};\n",[1069],{"type":706,"tag":721,"props":1070,"children":1071},{"__ignoreMap":723},[1072],{"type":711,"value":1067},{"type":706,"tag":707,"props":1074,"children":1075},{},[1076],{"type":711,"value":1077},"Ключевое здесь:",{"type":706,"tag":797,"props":1079,"children":1080},{},[1081,1106],{"type":706,"tag":801,"props":1082,"children":1083},{},[1084,1090,1092,1097,1099,1104],{"type":706,"tag":721,"props":1085,"children":1087},{"className":1086},[],[1088],{"type":711,"value":1089},"reverse()",{"type":711,"value":1091}," ",{"type":706,"tag":780,"props":1093,"children":1094},{},[1095],{"type":711,"value":1096},"мутирует",{"type":711,"value":1098}," исходный массив, то есть меняет порядок элементов ",{"type":706,"tag":815,"props":1100,"children":1101},{},[1102],{"type":711,"value":1103},"внутри того же объекта массива",{"type":711,"value":1105},".",{"type":706,"tag":801,"props":1107,"children":1108},{},[1109,1115,1117,1123],{"type":706,"tag":721,"props":1110,"children":1112},{"className":1111},[],[1113],{"type":711,"value":1114},"[...list.reverse()]",{"type":711,"value":1116}," создаёт новый массив, но уже из перевёрнутого исходного. Итоговое новое состояние по значениям: ",{"type":706,"tag":721,"props":1118,"children":1120},{"className":1119},[],[1121],{"type":711,"value":1122},"['b','a']",{"type":711,"value":1105},{"type":706,"tag":707,"props":1125,"children":1126},{},[1127],{"type":711,"value":1128},"Следующий рендер вернёт:",{"type":706,"tag":714,"props":1130,"children":1133},{"className":1131,"code":1132,"language":711},[717],"\u003Cdiv key={0}>b\u003C/div>\n\u003Cdiv key={1}>a\u003C/div>\n",[1134],{"type":706,"tag":721,"props":1135,"children":1136},{"__ignoreMap":723},[1137],{"type":711,"value":1132},{"type":706,"tag":707,"props":1139,"children":1140},{},[1141],{"type":711,"value":1142},"Теперь важно, как React сопоставит “старое” и “новое”:",{"type":706,"tag":898,"props":1144,"children":1145},{},[1146,1174],{"type":706,"tag":801,"props":1147,"children":1148},{},[1149,1151,1157,1159,1165,1167,1173],{"type":711,"value":1150},"Элемент с ",{"type":706,"tag":721,"props":1152,"children":1154},{"className":1153},[],[1155],{"type":711,"value":1156},"key={0}",{"type":711,"value":1158}," был и остался, значит DOM-узел для первого ",{"type":706,"tag":721,"props":1160,"children":1162},{"className":1161},[],[1163],{"type":711,"value":1164},"div",{"type":711,"value":1166}," переиспользуется, а меняется только текст: ",{"type":706,"tag":721,"props":1168,"children":1170},{"className":1169},[],[1171],{"type":711,"value":1172},"a → b",{"type":711,"value":1105},{"type":706,"tag":801,"props":1175,"children":1176},{},[1177,1178,1184,1186,1191,1192,1198],{"type":711,"value":1150},{"type":706,"tag":721,"props":1179,"children":1181},{"className":1180},[],[1182],{"type":711,"value":1183},"key={1}",{"type":711,"value":1185}," был и остался, значит DOM-узел для второго ",{"type":706,"tag":721,"props":1187,"children":1189},{"className":1188},[],[1190],{"type":711,"value":1164},{"type":711,"value":1166},{"type":706,"tag":721,"props":1193,"children":1195},{"className":1194},[],[1196],{"type":711,"value":1197},"b → a",{"type":711,"value":1105},{"type":706,"tag":707,"props":1200,"children":1201},{},[1202,1204,1209,1211,1216,1218,1224,1226,1232],{"type":711,"value":1203},"То есть ",{"type":706,"tag":780,"props":1205,"children":1206},{},[1207],{"type":711,"value":1208},"физического переставления",{"type":711,"value":1210}," двух ",{"type":706,"tag":721,"props":1212,"children":1214},{"className":1213},[],[1215],{"type":711,"value":1164},{"type":711,"value":1217}," местами в DOM не происходит, потому что с точки зрения ключей порядок не “переехал”: ключ ",{"type":706,"tag":721,"props":1219,"children":1221},{"className":1220},[],[1222],{"type":711,"value":1223},"0",{"type":711,"value":1225}," как был в первой позиции, так и остался в первой позиции, и аналогично ключ ",{"type":706,"tag":721,"props":1227,"children":1229},{"className":1228},[],[1230],{"type":711,"value":1231},"1",{"type":711,"value":1105},{"data":1234,"body":1235},{},{"type":703,"children":1236},[1237],{"type":706,"tag":707,"props":1238,"children":1239},{},[1240,1242,1247,1249,1254,1255,1260],{"type":711,"value":1241},"Полное удаление и создание новых ",{"type":706,"tag":721,"props":1243,"children":1245},{"className":1244},[],[1246],{"type":711,"value":1164},{"type":711,"value":1248}," обычно происходит, когда React не может сопоставить элементы (например, ключи изменились или отсутствуют, и структура/типы элементов не совпадают). Здесь ключи совпадают (",{"type":706,"tag":721,"props":1250,"children":1252},{"className":1251},[],[1253],{"type":711,"value":1223},{"type":711,"value":821},{"type":706,"tag":721,"props":1256,"children":1258},{"className":1257},[],[1259],{"type":711,"value":1231},{"type":711,"value":1261},"), поэтому выгоднее обновить текст внутри существующих узлов.",{"data":1263,"body":1264},{},{"type":703,"children":1265},[1266],{"type":706,"tag":707,"props":1267,"children":1268},{},[1269,1271,1276],{"type":711,"value":1270},"Виртуальный DOM не означает “реальный DOM не меняется”. Наоборот: виртуальное сравнение нужно, чтобы ",{"type":706,"tag":815,"props":1272,"children":1273},{},[1274],{"type":711,"value":1275},"правильно и эффективно",{"type":711,"value":1277}," обновить реальный DOM. Здесь данные изменились, значит изменения попадут и в реальный DOM.",{"data":1279,"body":1280},{},{"type":703,"children":1281},[1282],{"type":706,"tag":707,"props":1283,"children":1284},{},[1285,1287,1293,1294,1300,1302,1308],{"type":711,"value":1286},"Чтобы React “физически” переставил DOM-узлы, нужно, чтобы идентичности элементов были привязаны к данным (например, ",{"type":706,"tag":721,"props":1288,"children":1290},{"className":1289},[],[1291],{"type":711,"value":1292},"key=\"a\"",{"type":711,"value":821},{"type":706,"tag":721,"props":1295,"children":1297},{"className":1296},[],[1298],{"type":711,"value":1299},"key=\"b\"",{"type":711,"value":1301},"), а не к позициям. При ",{"type":706,"tag":721,"props":1303,"children":1305},{"className":1304},[],[1306],{"type":711,"value":1307},"key={index}",{"type":711,"value":1309}," идентичность привязана к месту, поэтому React обновляет содержимое, а не меняет порядок узлов.",{"data":1311,"body":1312},{},{"type":703,"children":1313},[1314,1319,1328],{"type":706,"tag":707,"props":1315,"children":1316},{},[1317],{"type":711,"value":1318},"Если элементы списка имеют уникальные значения, ключ можно привязать к значению:",{"type":706,"tag":714,"props":1320,"children":1323},{"className":1321,"code":1322,"language":711},[717],"{list.map((txt) => (\n  \u003Cdiv key={txt}>{txt}\u003C/div>\n))}\n",[1324],{"type":706,"tag":721,"props":1325,"children":1326},{"__ignoreMap":723},[1327],{"type":711,"value":1322},{"type":706,"tag":707,"props":1329,"children":1330},{},[1331,1333,1339,1341,1347,1349,1355],{"type":711,"value":1332},"Тогда при переходе ",{"type":706,"tag":721,"props":1334,"children":1336},{"className":1335},[],[1337],{"type":711,"value":1338},"['a','b'] → ['b','a']",{"type":711,"value":1340}," React будет видеть, что элемент с ключом ",{"type":706,"tag":721,"props":1342,"children":1344},{"className":1343},[],[1345],{"type":711,"value":1346},"b",{"type":711,"value":1348}," должен оказаться первым, а элемент с ключом ",{"type":706,"tag":721,"props":1350,"children":1352},{"className":1351},[],[1353],{"type":711,"value":1354},"a",{"type":711,"value":1356}," — вторым, и сможет корректно отразить перестановку (в терминах reconciliation это будет переупорядочивание по ключам).",{"data":1358,"body":1359},{},{"type":703,"children":1360},[1361],{"type":706,"tag":707,"props":1362,"children":1363},{},[1364,1366,1371],{"type":711,"value":1365},"Отдельно следует помнить, что ",{"type":706,"tag":721,"props":1367,"children":1369},{"className":1368},[],[1370],{"type":711,"value":1089},{"type":711,"value":1372}," мутирует массив. Для предсказуемости состояния обычно следует избегать мутаций и делать немутирующие преобразования.",{"data":1374,"body":1375},{},{"type":703,"children":1376},[1377,1382],{"type":706,"tag":707,"props":1378,"children":1379},{},[1380],{"type":711,"value":1381},"Например, без мутации:",{"type":706,"tag":714,"props":1383,"children":1386},{"className":1384,"code":1385,"language":711},[717],"const rotateList = () => {\n  setList(prev => [...prev].reverse());\n};\n",[1387],{"type":706,"tag":721,"props":1388,"children":1389},{"__ignoreMap":723},[1390],{"type":711,"value":1385},{"data":1392,"body":1393},{},{"type":703,"children":1394},[1395],{"type":706,"tag":707,"props":1396,"children":1397},{},[1398,1399,1404,1406,1411,1413,1418,1420,1426,1428,1434],{"type":711,"value":919},{"type":706,"tag":721,"props":1400,"children":1402},{"className":1401},[],[1403],{"type":711,"value":1307},{"type":711,"value":1405}," React считает элементы с одинаковыми индексами “теми же” элементами между рендерами, поэтому после ",{"type":706,"tag":721,"props":1407,"children":1409},{"className":1408},[],[1410],{"type":711,"value":1089},{"type":711,"value":1412}," два ",{"type":706,"tag":721,"props":1414,"children":1416},{"className":1415},[],[1417],{"type":711,"value":1164},{"type":711,"value":1419}," в DOM остаются на своих местах, а меняются только их текстовые узлы: первый становится ",{"type":706,"tag":721,"props":1421,"children":1423},{"className":1422},[],[1424],{"type":711,"value":1425},"'b'",{"type":711,"value":1427},", второй — ",{"type":706,"tag":721,"props":1429,"children":1431},{"className":1430},[],[1432],{"type":711,"value":1433},"'a'",{"type":711,"value":1105},1775735655417]