JS Flashcards
Назовите 3 любых метода функции
Функция-объект. Методы и свойства есть у объектов. В целом это говорит, что мы можем к методу функции обращаться через точку, как и к свойству объекта.
- f.length - сколько аргументов принимает функция
- f.bind - переводится, как связывать. То есть этот метод позволяет связать объект person с ключевым словом this во внешней функции через вспомогательную функцию.
const person = { // объект
firstname: ‘James’,
lastname: ‘Murray’,
showFullName: function(){
return this.firstname + ‘ ‘ + this.lastname;
}
}
function getSkills(s1, s2){ // функция, которую хотим связать с объектом
console.log(this.showFullName() +’ has skills: ‘+s1+’, ‘+s2);
}
let personSkills = getSkills.bind(person);
//Вызываем метод bind у копии нашей функции, где аргумент будет объект. Теперь personSkills - новая функция, которая при вызове устанавливает в качестве контекста выполнения this предоставленное значение.
personSkills(‘HTML/CSS’, ‘JavaScript’);
// Вызываем новую функцию, теперь в функции getSkills, this - объект person
//или 2-м способом, указав параметры вызова функции сразу
let personSkills = getSkills.bind(person, ‘HTML/CSS’, ‘JavaScript’);
personSkills();
// Можно так же связать другой this c копией функции:
const newObj = { firstname: ‘Tim’,
lastname: ‘Tock’,
showFullName: function(){
return this.firstname + ‘ ‘ + this.lastname;
}}
let personSkills2 = getSkills.bind(newObj );
// создали новую функцию и передали другой объект
personSkills2 (‘React\Redux’, ‘TypeScript’);
// this присваивается один раз, по этому мы не можем переприсваивать дальше с помощью bind его. Это касается одной и той же функции, например, personSkills . Мы не можем вот так по цепочке переприсвоить -
let personSkills = getSkills.bind(person).bind(person2).bind(person3)
- f.call - Отличием метода call() от bind() является то, что нет необходимости создавать вспомогательную функцию для того, чтобы передать в качестве this нужный объект.
Метод call() вызывает функцию с указанным значением this и индивидуально предоставленными аргументами.
getSkills.call(person, ‘PHP’, ‘Python’); //James Murray has skills: PHP, Python
// мы вызвали у нашей функции метод call, передали объект-person в качестве this и два аргумента, которые принимает наша функция.
В отличие от bind(), call() не копирует функцию. Он позволяет передавать объект в качестве this и любые аргументы, а затем немедленно вызывает функцию.
- f.apply - Методы apply() и call() практически идентичны при работе с выставлением значения this, за исключением того, что передаём параметры функции в apply() как массив, в то время, как в call(), параметры передаются в индивидуальном порядке.
getSkills.apply(person, [‘C++’, ‘C#’]); //James Murray has skills: C++, C#
Что такое рекурсия?
Рекурсия - функция, которая вызывает внутри себя себя же. Рекурсия должна иметь внутри себя условия- ограничения, иначе вызов функции будет бесконечен.
чем отличает == от ===?
Оператор == сравнивает на равенство, а вот === — на идентичность.
Тройное равенство не приводит два значения к одному типу.
false == 0 - true /псевдоложь (‘‘,0,false,[])
true == 1 - true
false ===0 - false / не идентичны типы
true == 1 - false
При сравнении строки с числом, JS попытается строку преобразовать в число - ‘01’ == 1 - true (1==1)
Boolean - проверяет на булевое знаяение:
let a = 0; - 0=false
alert( Boolean(a) ); // false
let b = “0”; - “0”-непустая строка = true
alert( Boolean(b) ); // true
alert(a == b); // true! - JS попытается преобразовать строку в число, а значит 0==0 - true. При строгом равенстве будет false, тк разные типы данных.
null == undefined - true
null === undefined - false
При использовании математических операторов и других операторов сравнения < > <= >=: значения null/undefined преобразуются к числам: null становится 0, а undefined – NaN.
Зачем нужен и у кого он есть метод addEventListener?
addEventListener позволяет повесить обработчик событий на ДОМ-элемент. Событие наступает тогда, когда происходит клик мыши по элементу, нажимает на определенную клавишу, наводит на элемент. Обработчик - функция, которая вызовется в момент события.
Есть метод onClick, он позволяет повесить обработчик события, если мы попытаемся повесить второй обработчик с таким же событием на элемент, то у элемента теперь будет более новый обработчик события. Таким образом, onClick позволяет повесить только один обработчик на событие.
Метод addEventListener позволяет добавлять несколько обработчиков на одно событие одного элемента, например:
function handler1() {
alert(‘Спасибо!’);
};
function handler2() {
alert(‘Спасибо ещё раз!’);
}
elem.onclick = () => alert(“Привет”);
elem.addEventListener(“click”, handler1); // Спасибо!
elem.addEventListener(“click”, handler2); // Спасибо ещё раз!
Очищать обработчики событий важно, потому что каждый обработчик занимает место в памяти и выполняется всякий раз, когда срабатывает событие. Если не убирать неиспользуемые обработчики событий, то можно столкнуться с неожиданным поведением. Например, один из старых обработчиков будет мешать всплытию события наверх, и другой обработчик не будет работать.
👇
Хорошим тоном считается убирать обработчик сразу же, как он перестал быть нужен.
Всегда сохраняйте функцию-обработчик в переменную чтобы позже убрать обработчик. !!!!!
const handleMouseClick = (event) =>{
//обязательно в переменную или если это функция - Function Declaration, то в removeEventListener записываем имя функции, как и переменную
console.log(‘Вы нажали на элемент:’, event.target)
}
window.addEventListener(‘click’, handleMouseClick, true)
// Ничего не передаем в опциях в третьем аргументе
window.removeEventListener(‘click’, handleMouseClick)
Что такое NodeJS?
Node.js — не отдельный язык программирования, а платформа для использования JavaScript на стороне сервера для веб-страниц и веб-приложений, а также для программ командной строки.
С помощью Node.js реализуется парадигма «JavaScript для всего». Она предполагает использование одного языка программирования для разработки веб-приложений вместо применения разных языков для работы над фронтендом и бэкендом.
В Node.js используется асинхронное программирование, те позволяет продолжить обработку других задач, не дожидаясь завершения передачи данных.
Имеет пакетный менеджер NPM, который содержит множество библиотек.
Что такое замовызывающаяся функция?
Обычно она не имеет названия:
(просто засунули в переменную, чтобы получить результат из return)
const data = (function(){
let a = 100
let b = 90
})()
И нужна, чтобы ограничить области видимости. И теперь переменные а и b в глобальной области видимости недоступны, чтобы их поменять.
Ну и если хотим выкинуть наружу из функции какие-то данные, то return.
Расшифруйте аббревиатуру БЭМ
Это методология, разработал Яндекс.
БЭМ (Блок, Элемент, Модификатор) — компонентный подход к веб-разработке. Принцип - разделение интерфейса на независимые блоки.
Он позволяет легко и быстро разрабатывать интерфейсы любой сложности и повторно использовать существующий код, избегая «Copy-Paste».
Блок - Функционально независимый компонент страницы, который может быть повторно использован. В HTML блоки представлены атрибутом class.
Название блока характеризует смысл («что это?» — «меню»: menu, «кнопка»: button)
Элемент - Составная часть блока, которая не может использоваться в отрыве от него.
Название элемента характеризует смысл («что это?» — «пункт»: item, «текст»: text)
Элемент — всегда часть блока, а не другого элемента. Это означает, что в названии элементов нельзя прописывать иерархию вида block__elem1__elem2. Только block__elem1 и block__elem2
Модификатор - Cущность, определяющая внешний вид, состояние или поведение блока либо элемента.
Название модификатора характеризует внешний вид («какой размер?», «какая тема?»
состояние («чем отличается от прочих?» — «отключен» и поведение («как ведет себя?», «как взаимодействует с пользователем?» — «направление»
Согласно принципу REST API задокументируй еndPoint , удаляющий конкретный репозиторий конкретного пользователя
Мы должны знать куда слать - это URL,
какой тип запроса - type,
что в ответе будет - response: статус запроса - status
- Какой URL у нас будет:
‘<базовый>/users/:id/repozitories/rep-:id'
Сначала базовый url, потом список юзеров, потом находим определенного юзера по id, затем заходим в список его репозиториев и затем удаляем по id конкретный репозиторий.</базовый> - Хотим удалить этот репозиторий, значит нам нужно знать какой тип type (http методы) - DELETE
- status может вернуться 200 - если удаление произошло, точнее 204 - нет содержимого для ответа на запрос, но заголовки ответа, которые могут быть полезны, присылаются., тк мы удалили репозиторий.
Или если нет прав доступа к серверу, чтобы удалить - 403
Дополнительно:
POST(создать новый репозиторий)-‘<базовый>/users/:id/repozitories/'
Сначала базовый url, потом список юзеров, потом находим определенного юзера по id, затем заходим в список его репозиториев и уже создаем новый репозиторий</базовый>
GET(получить конкретный репозиторий) - ‘<базовый>/users/:id/repozitories/rep-:id'</базовый>
Маршрут (Route - роут) — это «имя», которое отсылает работу API к определенным эндпоинтам. Если упростить, то можно сказать, что маршрут - это URL к которому можно обратиться разными HTTP методами. Маршрут может иметь несколько эндпоинтов.
Эндпоинт (Endpoint - конечная точка) — это само обращение к маршруту отдельным HTTP методом. Эндпоинт выполняют конкретную задачу, принимают параметры и возвращают данные Клиенту.
http://example.com/wp-json/wp/v2/posts/123:
Здесь wp/v2/posts/123 — это маршрут, а /wp-json — это базовый путь самого REST API.
Этот маршрут имеет 3 эндпоинта:
GET — запускает метод get_item() и возвращает данные поста Клиенту.
PUT|PATCH|POST — запускает метод update_item(), обновляет данные и возвращает их Клиенту.
DELETE — запускает метод delete_item(), удаляет пост и возвращает только что удаленные данные Клиенту.
Найти отличие между HTTP1 и HTTP2
Семантика осталась прежней, все основные понятия остались такими же: заголовки, методы, url-адрес.
Изменяет лишь способ упаковки данных и способ передачи запроса и ответа.
1.Способ упаковки:
- Cпособ передачи запроса и ответа:
HTTP2 может организовать в рамках одного соединения с сервером параллельно обмен несколькими сообщениями(так называемые стримы).
Называется этот параллельный обмен сообщениями в рамках одного подключения - Мультиплексирование.
В HTTP1 нет многопоточности, необходимо было ждать.
Раньше нужно было на сервере склеивать в один js-файл другие js-файлы(аналогично и с картинками, склеивали в большой спрайт) для того, чтобы фронтенд запрашивал один этот файл. Если бы не склеивали, то пришлось бы запрашивать каждый раз по отдельности эти js-файлы,при этом соединение каждый раз открывается\закрывается. Плюс браузер ограничивает одновременное количество запросов к одному домену.
Оч много времени тратилось на обмен данными.
https://habr.com/ru/articles/739166/
В чем отличия HTTP1, HTTP2 , HTTP3
Что такое DNS и как он работает?
DNS (Domain name system) — это система, которая позволяет писать человекопонятным языком названия сайтов(incubator.ru - доменное имя) в поисковую строку браузера, а браузеру находить нужный сайт и отображать его.
DNS занимается тем, что преобразует названия сайтов — доменные имена(incubator.ru), которые вводят в поисковую строку браузера в IP-адреса конкретных серверов. Если бы не было DNS, вам бы пришлось запоминать IP-адреса нужных вам ресурсов и вводить их вручную в браузер.
Сведения о доменах(incubator.ru) и их связи с IP-адресами находятся в распределенной базе данных, которая хранится на DNS-серверах, образующих иерархию.
Когда вы вводите запрос в поисковую строку браузера, например, 1cloud.ru — браузер сначала проверит наличие DNS-записи на вашем локальном компьютере в файле hosts, если там нет нужного адреса, запрос направляется дальше — на локальный DNS-сервер интернет-провайдера пользователя, если и там записи нет, запрос уходит выше на сервера географических зон.
Как только нужная DNS-запись найдена, браузер получает IP-адрес, на который посылает запрос. В ответ приходит web-страница.
Получается, что DNS-запрос поднимается от локальных хранилищ данных до самого верхнего уровня, это быстрее, чем делать запрос сначала к корневому DNS-серверу и идти вниз.
Локальный DNS-сервер(локальное хранилище) опрашивает DNS-сервера второго, верхнего и корневого уровней, а не браузер! Он находит сведения о домене, возвращает их браузеру и записывает данные в кеш на 24 часа. В итоге при следующем обращении к этому сайту, он просто вернет данные из кеша и сайт загрузится быстрее.
Что такое CDN (Content Delivery Network)?
это группа особым образом настроенных серверов, расположенных в разных геоточках. Серверы выступают в качестве узлов, которые позволяют быстро загружать контент ближайшим пользователям.
Таким образом, разветвленная сеть CDN с расположенными неподалеку серверами позволяет значительно сократить время загрузки удаленных сайтов.
То есть, когда на московский сайт заходит посетитель из Сахалина или Хабаровска, то контент будет загружаться не из Москвы, а из Владивостока. Естественно, это положительно скажется на скорости загрузки сайта.
CDN может отдавать любой статический контент: картинки, видео, JS-скрипты и многое другое. Кэшированием контента управляет администратор. Он может настроить принудительную загрузку контента на CDN-сервера, разбить контент на категории и назначить приоритетность кэширования, задать время жизни кэша и многое другое.
Итог: делаются копии загрузившеегося контента по всем таким серверам и уже с ближайшего сервера отправляется контент до пользователя.
Что такое Event Loop?
Это бесконечный цикл, в котором движок JavaScript ожидает задачи, исполняет их и снова ожидает появления новых.
Общий алгоритм движка:
-Пока есть задачи: выполнить их, начиная с самой старой.
-Бездействовать до появления новой задачи, а затем перейти к пункту 1.
Задачи поступают на выполнение – движок выполняет их – затем ожидает новые задачи (во время ожидания практически не нагружая процессор компьютера).
Может так случиться, что задача поступает, когда движок занят чем-то другим, тогда она ставится в очередь.
Очередь, которую формируют такие задачи, называют «очередью макрозадач» .
Макрозадачи - setTimeout, eventListener и т.д.
Например, когда движок занят выполнением скрипта-
, пользователь может передвинуть мышь, тем самым вызвав появление события mousemove, или может истечь таймер, установленный setTimeout, и т.п. Эти задачи формируют очередь.
Задачи из очереди исполняются по правилу «первым пришёл – первым ушёл». Когда браузер заканчивает выполнение скрипта, он обрабатывает событие mousemove, затем выполняет обработчик, заданный setTimeout, и так далее.
Пример, подсветка синтаксиса - трудоемкая задача для движка, особенно, если текста много. Пока он занят выполнением, то он не сможет обрабатывать пользовательские события, связанные с DOM.
Т.е. пользователь нажмет на кнопку, но ничего не произойдет, будет подвисание, тк движок продолжает обрабатывать старую задачу.
Избежать этого поможет setTimeout, таким образом разобьем задачу на несколько простых. Например, задать подсветку для первых сто страниц, а затем запланировать setTimeout с нулевой задержкой для разметки следующих сто страниц. Если произойдет пользовательские событие, то оно встанет в очередь после задачи с первыми сто страницами и выполнится по ее завершению, затем будет выполнятся следующие сто страниц.
Дополнительно: помним, в браузере есть минимальная задержка в 4 миллисекунды при множестве вложенных вызовов setTimeout. Даже если мы указываем задержку 0, на самом деле она будет равна 4 мс (или чуть больше). Поэтому чем раньше мы запланируем выполнение – тем быстрее выполнится код.
Микрозадачи:
Микрозадачи приходят только из кода. Обычно они создаются промисами: выполнение обработчика .then/catch/finally становится микрозадачей. Микрозадачи также используются «под капотом» await, т.к. это форма обработки промиса.
Сразу после каждой макрозадачи движок исполняет все задачи из очереди микрозадач перед тем, как выполнить следующую макрозадачу или отобразить изменения на странице, или сделать что-то ещё.
Все микрозадачи завершаются до обработки каких-либо событий или очереди рендеринга, или перехода к другой макрозадаче.
Например:
setTimeout(() => alert(“timeout”)); - 3 т.к. макрозадача
Promise.resolve()
.then(() => alert(“promise”)); -2 . т.к. здесь .then
alert(“code”); - 1 т.к. синхронный код
Какой здесь будет порядок?
-code появляется первым, т.к. это обычный синхронный вызов.
-promise появляется вторым, потому что .then проходит через очередь микрозадач и выполняется после текущего синхронного кода.
-timeout появляется последним, потому что это макрозадача.
Итого: полный алгоритм
1.Выбрать и исполнить старейшую задачу из очереди мАкрозадач (например, «script»).
Принцип - первый зашел-первый вышел.
- Исполнить все мИкрозадачи:
Пока очередь микрозадач не пуста: - Выбрать из очереди и исполнить старейшую микрозадачу(Принцип - первый зашел-первый вышел.) - Отрисовать изменения страницы, если они есть.
- Если очередь макрозадач пуста – подождать,
пока появится макрозадача. - Перейти к шагу 1.
Так же есть еще одна очередь помимо макро и микрозадач, это очередь рендера, она состоит из
–requestAnimationFrame
–style
–layot
–paint
–composite
На этих этапах браузер пересчитывает стили, как расположить элементы, их размеры, применение цвета, фона и т.д.
Если сравнивать очередь макрозадач и очередь рендера, то в приоритете будет очередь рендера, например:
очередь макро | очередь рендера
макро2 | рендер 2
макро1 | рендер 1
Если после макро1 собралась очередь из рендера, то они(рендер 1 и рендер 2) выполнятся ПЕРЕД макро2. Если же в момент выполнения очереди рендера присоединится еще один - рендер3, то он уже будет выполнятся после выполнения макро2, НО перед выполнением макро3, если такая появится.
Приоритеты:
1 - микротаски, выполняется вся очередь микротасок перед выполнением макротаски и очереди рендера. Если вовремя выполнения микротасок приходят еще, то они продолжатся выполнятся, пока очередь не опустошится.
2 - очередь рендера, выполняются перед макротасками и после выполнения всей очередь микротасок. Если во время выполнения этой очереди приходят еще новые рендеры, то они откладываются на следующее выполнение перед следующей макротаской.
3 - очередь макротасок.
Важно!!! Если приходит синхронная операция, то она прерывает все очереди и выполнится в Стеке вызова мгновенно, даже если в это время выполнялась очередь микротасок.
Создание промиса - new Promise - та же синхронная операция, а уже обработка промиса, например, .then - это уже ассинхронщина(микротаска)
Такой цикл состоит из:
–Call Stack(стек вызовов), где действует правило “Первый зашел-первый вышел”. Туда попадают синхронные операции.
–Queue(очередь), куда попадают ассинхронные операции, там выполняются. И далее=>
–Callback queue(очередь обратного вызова), куда попадают выполненные ассинхронные операции и ждут свой очереди, пока все синхронные операции не уйдут и Call Stack не очистится, чтобы попасть в Call Stack, отработать и выйти оттуда.
Пример1: здесь рассм-ся с ассинх. операциями
console.log(‘a’) - зашел-вышел
setTimeout(()=>console.log(‘d’)) -попал в Queue
console.log(‘b’) - зашел-вышел
console.log(‘c’) - зашел-вышел
Пример2: здесь синхронные операции
function a(){} - пятый зашел и вышел
function b(){ a() }- четвертый зашел и остался
function c(){ b() }- третий зашел и остался
function d(){ c() } - второй зашел и остался
function e(){ d() } - первый зашел и остался
e()
Call Stack будет таким:
function a() последний зашел-первый вышел
function b()
function c()
function d()
function e() первый зашел-последний вышел =>
Почему? Потому что для выполнения ему необходимо дождаться выполнение функции d() и т.д. для выполнения функции d() необходимо выполнение функции c()
Что такое git?
Git — это система контроля версиями.
Git позволяет разработчикам создавать репозитории, в которых хранятся файлы проекта и история их изменений.
Каждый разработчик может клонировать репозиторий на своем компьютере и работать над проектом независимо. Можно вносить изменения в файлы, добавлять новые файлы, удалять или изменять существующие.
Git имеет возможность ветвления и слияния. Разработчики могут создавать отдельные ветки, чтобы работать над кодом, не затрагивая основную ветку проекта. После завершения работы ветки могут быть объединены с основной веткой, чтобы внести внесенные изменения.
Чем отличается localStorage от sessionStorage?
localStorage и sessionStorage - объекты-хранилища, позволяющие хранить пары ключ/значение в браузере. Они имеют методы, как и другие объекты:
setItem(key, value) – сохранить пару ключ/значение.
getItem(key) – получить данные по ключу key.
removeItem(key) – удалить данные с ключом key.
clear() – удалить всё.
key(index) – получить ключ на заданной позиции.
length – количество элементов в хранилище.
Local Storage - даже после перезапуска браузера (до ручной очистки данных браузера или до установленной даты)
Пример: токен пользователя
Session Storage -сохраняются после обновления страницы, но не после закрытия/открытия вкладки. Существует только в рамках текущей вкладки браузера. Другая вкладка с той же страницей будет иметь другое хранилище.
Пример может быть банковские транзакции, пополнение форм
Чем отличается Function Declaration от Function expression?
Во-первых, синтаксис: как отличить их друг от друга в коде.
Function Declaration: функция объявляется отдельной конструкцией «function…» в основном потоке кода.
Function Expression: функция, созданная внутри другого выражения или синтаксической конструкции. В данном случае функция создаётся в правой части «выражения присваивания» =:
Function Expression(функ.выражение) создаётся, когда выполнение доходит до него, и затем уже может использоваться.
После того, как поток выполнения достигнет правой части выражения присваивания let sum = function… – с этого момента, функция считается созданной и может быть использована (присвоена переменной, вызвана и т.д. ).
Function Declaration может быть вызвана раньше, чем она объявлена.
Другими словами, когда движок JavaScript готовится выполнять скрипт или блок кода, прежде всего он ищет в нём Function Declaration и создаёт все такие функции. Можно считать этот процесс «стадией инициализации».
И только после того, как все объявления Function Declaration будут обработаны, продолжится выполнение.
В результате функции, созданные как Function Declaration, могут быть вызваны раньше своих определений.
Речь идет о “всплытии” (hoisting):
При использовании Function Declaration, объявление функции поднимается вверх текущего контекста выполнения кода.
Это означает, что функцию можно вызывать до того, как она фактически была объявлена в коде.
example();
// Работает, потому что Function Declaration поднимается вверх
function example() {
console.log(“Hello, World!”);
}
В случае Function Expression, переменная example поднимается вверх, но само присваивание (и объявление функции) остается на месте в коде. Поэтому, если вы попытаетесь вызвать функцию до строки с присваиванием, вы получите ошибку.
// Не работает, потому что присваивание (и объявление функции) ещё не произошло
example();
var example = function() {
console.log(“Hello, World!”);
};
typeof NaN
typeof undefined
typeof null
typeof Bigint
typeof []
typeof Function(){}
оператор “нулевого слияния” (??)
typeof NaN = number / сравниваем NaN = NaN только через isNaN(NaN)
typeof undefined = undefined
typeof null = object
typeof Bigint = bigint
typeof [] = object
typeof Function(){} = function
оператор “нулевого слияния” (??), который позволяет выбрать первое из определенных значений (не равных null или undefined).
var myValue = null;
var result = myValue ?? “default”;
console.log(result); // “default”
Методы строк?
.toUpperCase()
.toLowerCase()
.length
str.indexOf(substr, pos) - ищет подстроку substr в строке str, начиная с позиции pos, и возвращает позицию, на которой располагается совпадение, либо -1 при отсутствии совпадений.
str.lastIndexOf(substr, position), который ищет с конца строки к её началу
str.includes(substr, pos) возвращает true, если в строке str есть подстрока substr, либо false, если нет.
str.startsWith(substr) и str.endsWith(substr) проверяют, соответственно, начинается ли и заканчивается ли строка определённой строкой
str.slice(start [, end]) - возвращает часть строки от start до (не включая) end.
.split - на массив
Что такое семантические теги?
Что такое семантические элементы?
Что такое не семантические элементы?
Что такое семантические элементы?
Это теги, которые предназначены для того, чтобы компьютерные программы (поисковые системы, сборщики информации, речевые браузеры и т. д.) понимали, какой тип информации заложен в данных тегах. Проще говоря, это как таблички в супермаркетах, которые указывают, где и какой находится отдел.
<header> <nav> <footer> <aside>
Что такое семантические элементы?
<form>, <table> и <article> – это семантические элементы: они четко определяют свое содержание.
Что такое не семантические элементы?
<div> и <span> являются не семантическими элементами. Они ничего не говорят нам об их содержании.
Теги помогают быстрее обрабатывать код поисковым роботам, вследствие чего у вашего сайта больше шансов попасть на первые страницы Google, Yandex и т.д.
</span></div></article></table></form></aside></footer></nav></header>
В чем разница протоколов HTTP и HTTPS?
И еще - вообще для чего нужен https , если на сайте не требуется вводить какие-то личные данные и тп?
«HTTP, или Hyper Text Transfer Protocol, — это протокол передачи гипертекстовой разметки(HTML), которая используется для передачи данных в интернете».
Протокол или интернет-протокол — это набор процедур или правил, позволяющих электронным устройствам взаимодействовать между собой.
(гипертекстовоя разметка - это HTML(HyperText Markup Language) ), язык гипертекстовой разметки текста. Он нужен, чтобы размещать на веб-странице элементы: текст, картинки, таблицы и видео. HTML как бы выстраивает визуальный фундамент сайта)
Когда мы набрали запрос и нажали ввод, браузер отправил этот запрос на веб-сервер.На веб-сервере хранятся статьи в виде картинок, HTML-документов, файлов с CSS-стилями и JavaScript-файлами. Также на веб-сервере установлено ПО, которое понимает HTTP-протокол.
Веб-сервер принимает запрос, обрабатывает, определяет, какие файлы отправить, и отдает их в ответ. Браузер принимает эти данные, интерпретирует и показывает нам в «человеческом» виде.
Каждое действие в блоге, например, переход по ссылке на статью, — это новый запрос серверу и новый ответ.
HTTPS — это не совсем протокол. Это расширение HTTP-протокола — объединение двух протоколов: HTTP и TLS.
Протокол TLS (Transport Layer Security) — криптографический. Это значит, что они позволяют шифровать данные, в нашем случае те, что передаются между браузером и сервером. Расшифровать эти данные могут только сервер и браузер, для всех остальных это будет набор нечитаемых символов.
Как работает шифрование:
У ресурса/сайта, поддерживающего HTTPS, есть TLS-сертификат, который выдается центром сертификации. Если у ресурса в адресной строке есть зеленый замок, соединение с ним защищено.
Посмотреть информацию о сертификате и его подлинности можно, нажав на значок.
TLS-сертификат — это подтверждение, что ресурс настоящий. Но могут быть исключения: сертификат может быть выдан легитимным центром на фишинговый сайт.
Браузер проверяет данные по своим спискам доверенных центров (список есть в каждом браузере), проверяет совпадение CN с доменным именем, даты выпуска и срока окончания сертификата, отсутствие в CRL, поддерживаемые алгоритмы, наличие издателя в списке доверенных корневых сертификатов и в списке доверенных издателей. В случае проблем на любой из этих проверок сертификат считается невалидным.
Если все хорошо, то браузер считает ресурс безопасным: они выбирают алгоритм шифрования, обмениваются ключом шифрования и потом данными по протоколу HTTP.
Сейчас в браузерах работает HSTS — HTTP Strict Transport Security. Это защитный механизм браузера, который принудительно переводит соединение из HTTP в HTTPS или обрывает HTTP-соединение.
Чаще всего ресурс на HTTP браузер просто не откроет, а выведет предупреждение. Например, в браузере Google Chrome незащищенные ресурсы блокируются еще с 2020 года.
Стандарт задают поисковики и веб-браузеры. Сейчас без зеленого значка у сайта в адресной строке к ресурсу не будет доверия у пользователей, если он вообще откроется в браузере. Поисковики настоятельно рекомендуют переходить на HTTPS. Например, Яндекс открыто сообщает о том, что сайты, не использующие сертификаты, будут ниже в поисковой выдаче.
И еще - вообще для чего нужен https , если на сайте не требуется вводить какие-то личные данные и тп?
Для того, чтобы в response-в ответ от сервера не дополнили какими-то неправильными данными.Например, реклама
Что такое WebSoket?
Это протокол.
Протокол или интернет-протокол — это набор процедур или правил, позволяющих электронным устройствам взаимодействовать между собой.
Какие протоколы бывают :
HTTP, HTTPS
WebSoket, WWS
FTP,«File Transfer Protocol»позволяют пересылать файлы с одного устройства (например, компьютера Mac, Windows или Linux ) на другое.
SMTP, Simple Mail Transfer Protocol простой протокол связи, применяемый с целью пересылки электронных писем с сервера отправителя на сервер получателя.
POP3 Post Office Protocol почтовый протокол, с помощью которого загружаются сообщения на почтовый клиент с удаленного сервера.
Пишется протокол в адресной строке вначале доменного имени.
Зачему нужны разные протоколы? Разные программы взаимодействуют между собой через разные протоколы.
Сервер по запросу отправляет ответ HTTP.
При таком протоколе как бы выглядела переписка:
человек отправляет сообщение оно уходит на сервер, и чтобы получить сообщение другому человеку, ему нужно отправлять так же запрос на сервер, чтобы получить это сообщение.
WebSoket: Реактивно реагирует что происходит на сервере. Сервер тоже отправляет запросы клиенту. У HTTP тоже есть по аналогии, но WebSoket популярнее.
Как это работает?
Клиент создает канал к серверу и по этому каналу могут оба они делают запросы-реквесты друг другу. Например, нам отправляют личное сообщение, сервер это увидел и по каналу мгновенно отправляет его нам.
try catch finally
try - выполняется код
catch - если в процессе выполнения кода возникнет ошибка, то попадем сюда. Здесь мы можем как-то проанализировать ошибку.
finally - если нет ошибок , то попадаем сюда
И далее уже вниз идем по коду дальше.
Можно обойтись и без finally , просто прописываем необходимый код, который нужно проверить в try , пишем дополнительно catch и уже дальше пойдет выполняться код ниже, если нет ошибок.
Но в некоторых случаях finally нужен, например сёркл(крутилка при загрузки), если нет ошибок, то ее нужно убрать, если возникнет ошибка, ее так же нужно убрать. То есть если возникнет ошибка, то мы в код ниже не попадем, а нам нужно убрать крутилку. По этому finally и нужен.
Для чего нужен Promise.all?
Promise.all([промис, промис, промис])
Если нам нужно запустить множество промисов параллельно и дождаться пока они все выполнятся. Например, загрузить несколько файлов одновременно и обработать результат , когда он готов. Придут данные так же по порядку, по которому мы прописывали промисы, даже если кто-то из них выполнится раньше другого.
.all - это метода класса промис, принимает массив промисов, вернет метод промис тогда, когда все промисы заресолвятся(resolve-выполнится тогда, когда завершилось успешно и получили результат, противоположно этому - rejected)
Передаем массив других промисов
Назовите минимум 3 метода жизненного цикла классовой компоненты?
Каждый компонент React проходит несколько стадий в процессе своей жизни:
он создается,
затем добавляется в DOM,
получает пропсы,
и, наконец, удаляется из дерева.
Этот процесс называют жизненным циклом компонента (Component Lifecycle).
React предоставляет набор методов, которые позволяют встроиться в этот процесс. Например, запуск часов логичнее всего сделать сразу после их отрисовки.
1 этап: Монтирование (Mounting):
Появление в HTML\рождение компоненты.
Если компонента отрисовалась\появилась в DOM, то произошел этот цикл.
Эти методы вызываются по порядку во время создания объекта и вставки его в DOM.
constructor()
static getDerivedStateFromProps()
render()
componentDidMount()
Как мы можем написать функцию, чтобы она сработала сразу же после рождения компоненты?
Можно использовать useEffect().
useEffect(()=>{ }, [ ]) - первый аргумент - коллбэк, который сработает, второй аргумент - зависимость, если он пустой, то наш коллбэк сработает 1 раз при рождении компоненты.
Что как правило происходит на стадии рождения?
Общение с бэкендом - если мы хотим сделать запрос на бэкенд, взять какие-то данные, например, список пользователей. Это самое лучше, что может происходить при рождении компоненты. Происходит это в useEffect().
2 этап: Обновление\появление (Updating)
Обновление может происходить при изменении свойств или состояния. Эти методы вызываются по порядку во время перерисовки:
static getDerivedStateFromProps()
shouldComponentUpdate()
render()
getSnapshotBeforeUpdate()
componentDidUpdate()
Что заставляет компоненту обновляться?
Изменение пропсов и изменение стейта.
Здесь опять же помогает это отследить useEffect().
useEffect(()=>{ }, [ ]) - первый аргумент - коллбэк, который сработает, если произошли изменения, второй аргумент - зависимость, там лежит стейт\пропсы, которые будут отслеживаться, произошли ли в них изменения, если да, то выполнится коллбэк. Если приходящие пропсы изменились, то произойдет перерисовка.
Внимание, этот useEffect первый раз вызовется при рождении компоненты, и далее будет вызываться тогда, когда произойдут изменения в стейте!
3 этап: Удаление или демонтирование (Unmounting)
Он вызывается во время удаления компонента из DOM.
Один метод:
componentWillUnmount()
Нередко в приложении возникает необходимость подисывается на различные ресурсы, а после окончания работы и отписываться от них. В этом случае мы можем использовать специальную форму хука useEffect():
useEffect(() => {
// код подписки на ресурс
unmountBtn.addEventListener(“click”, unmount);
return () => {
// код отписки от ресурса
unmountBtn.removeEventListener(“click”, unmount);
};
});
В начале функции хука идет подписка на ресурс, а далее оператор return возвращает функцию, которая выполняет отписку от ресурса.
Что такое PWA?
«Progressive Web Application» — прогрессивное веб-приложение.
Технология в web-разработке, которая визуально и функционально трансформирует сайт в приложение (мобильное приложение в браузере)»
По сути, это «прокачанная» копия веб-сайта, размещенная на устройстве пользователя и не требующая отдельной разработки для iOS или Android.
PWA — это сайты с расширенной функциональностью, которая позволяет им быть похожими на нативные мобильные приложения.
Работают эти приложения так же, как и обычные мобильные приложения: показывают Push-уведомления, работают в автономном офлайн-режиме, сохраняют данные локально. По внешнему виду они ничем не отличаются от нативных приложений и могут размещать иконку на рабочем столе (домашнем экране) для быстрого запуска.
PWA, как обычные сайты, размещаются на доменах с https-шифрованием. Таким образом поддерживается уникальность приложений, поскольку не бывает двух одинаковых доменов.
Все ли в js объекты?
Примитивы – не объекты.
У примитивов, кроме null и undefined, есть свои методы, но они не объекты.
Чтобы методы работали, при таком доступе создаётся специальный «объект-обёртка», который предоставляет нужную функциональность, а после удаляется.
array, object, function - это все объекты
Но при проверки через typeof function - это будет Function.
Так же при проверке через typeof null покажет Object, но это примитив. typeof null, дающее ‘object’, было ошибкой в ранней реализации JavaScript.
null показывает отсутствие какого-либо объектного значения.
Если вы видите null (присвоенное переменной или возвращенное функцией), то в этом месте должен быть объект, но по какой-то причине объект не был создан.
Не используйте оператор typeof для определения значения null. Как упоминалось ранее, используйте оператор строгого равенства myVar === null.
Пример:
// переменная foo существует, но она не имеет ни типа, ни значения:
> var foo = null; - переменная существует - это foo
// переменная foo не существует - она не была определена и никогда не инициализировалась:
> foo - undefined
Зачем нуден async/await?
Это синтаксический сахар над тем что уже есть.
Это нужно для работы с ассинхронным кодом.
В js есть удобная штука для работы с таким кодом -Promise. Это объект, который может находится в одном из трех состояний -
1.pending(ожидает, если результат еще не готов, ожиданиет завершения каких-то ассинхр.операций),
2.resolved(завершение, результат доступен, что-то завершилось сове выполнение, все прошло хорошо),
3.rejected(произошла ошибка в процессе выполнения, отклонен)
Как мы одного из трех состояний дожидаемся?
с помощью .then, т.е. чтобы получить ответ и его обработать, мы будем использовать цепочку then-ов:
promise.then( (response)=> … ).then((data)=> … )
Зачем нужен async/await?
Дожидание , когда промис зарезолвится(resolved), те мы с помощью await дожидаемся когда промис зарезолвится, а это ожидание может происходить только в ассинхр.функции - async.
Такой код выглядит короче, без этих вложенностей с коллбэками, нам не нужно использовать .then, теперь пишем так:
(async () => {
let response = await fetch(‘/article/promise-chaining/user.json’);
//получили промис
//если fetch не выполнится, то код ниже него не будет выполнятся
let user = await response.json();
//обработали в json
…
})(); -async/await всегда возвращает промис, так же необходимо такой код заворачивать в async , в данном случае можно обернуть анонимной самовызывающейся функцией.
Так же проще делать обработчку ошибок try\catch
Функция – это какой тип?
В JavaScript функции – это объекты. Значит это ссылочный тип данных.
Функции можно не только вызывать, но и использовать их как обычные объекты: добавлять/удалять свойства, передавать их по ссылке и т.д.
- Имя функции - методом .name
function sayHi() {
alert(“Hi”);
}
alert(sayHi.name); // sayHi
2.Метод «length» содержит количество параметров функции в её объявлении.
function f2(a, b) {}
alert(f2.length); // 2 - длина рассчитывается по количеству параметров
function many(a, b, …more) {}
alert(many.length); // 2 - rest-оператор не считается
3.Мы также можем добавить свои собственные свойства.
function sayHi() {
alert(“Hi”);
sayHi.counter++; // добавили свойство .counter
}
Что такое кэш?
Кэш позволяет хранить в папке на нашем жестком диске загружаемую с сайтов всю информацию (графическая, текстовая, мультимедийная) в тот момент, когда мы зашли на сайт впервые.
А когда заходим на сайт второй раз, то браузер проверяет содержимое сайта на наличие новых данных и подгружает их к нам. Остальная же информация берется для отображения именно из нашего кэша.
Для чего?
Во-первых, для повышения скорости загрузки сайта,
во-вторых, для снижения нагрузки на интернет-соединение, ведь доступ к данным в кэше осуществляется быстрее.
Кэш можно почистить в инструментах разработчика. Заходим в раздел Приложение =>
Хранилище => Удалить данные сайта
Что такое куки?
Куки тоже хранятся на нашем ПК, как и кэш, и представляют собой данные (как правило, их небольшой фрагмент).
Этот небольшой фрагмент отправляется сервером на наш компьютер при посещении сайта впервые.
Мы должны дать согласие на прием куки.
Выскакивает окошко для принятия куки, когда мы заходим на сайт впервые.
Главное отличие куки от кэша заключается в том, что каждый раз, когда мы повторно заходим на конкретный сайт, с которого нам уже был когда-то отправлен конкретный куки, наш браузер пересылает этот фрагмент данных серверу в составе HTTP-запроса.
Примеры:
1.Авторизация на сайте. Как известно большинство сайтов имеют авторизацию (ввод пароля, логина, телефона, почты и т. п.). Cookie могут применяться сервером для опознания ранее аутентифицированных пользователей.
- Корзина в интернет-магазинах. Если не использовать куки, при выборе товара и переходе на новую страницу товар может исчезнуть.
- Настройки. К примеру, мы выставили нужные настройки региона, языка и т. д. Без куки они могут сброситься и вернуться в статус значений по умолчанию.
Куки можно почистить в инструментах разработчика.
В приложение =>
То есть надо будет выбрать адрес сайта под строкой Cookie, нажать правую кнопку мыши, а потом «Clear».
Что такое SPA?
Браузер делает запрос на сервер, он отправляет один файл index.html и bundle.js
(В большинстве проектов собирают все javascript файлы (а иногда css и картинки тоже) в один очень большой bundle.js.(Сборщик модулей WebPack создает этот файл, собирая все файлы в единый файл). Сreate-react-app использует под капотом webpack со всеми необходимыми плагинами.)
После этого кликая по ссылкам в приложении, мы уже не заправшиваем у сервера новый HTML-файл и js-файл, можем запрашивать только какие-то API-данные в формате json или xml . Реакт сам рисует компоненты, которые необходимо отобразить.
Благодаря Реакт-роутеру, мы сможем отображать эти переходы к другим компонентам, вместо того, чтобы отправлять запрос на сервер.
Что такое DOM?
Браузер не работает с HTML-страницей напрямую как с текстом, а строит для этого DOM.!!!!!!!!!!!!!!!!!!!!
Document Object Model - это объектная модель документа , представляет собой древовидную структуру страницы, состоящую из узлов. Каждый узел в ней – это объект, который может иметь определённые свойства и методы. DOM-узлы образуются из всего, что есть в HTML: тегов, текстового контента, комментариев и т.д. Эти объекты связанным между собой иерархически, те родитель-ребенок и тд.
Корневым узлом DOM-дерева является объект document - входная точка в DOM: document=>html=> разделяется на: head и body => и т.д.
Каждый узел в DOM – это объект, который может иметь определённые свойства и методы.
На свойства часто ссылаются как на то, с чем необходимо что-либо сделать (например, название узла). document.innerHTML - отобразит текст, который содержится в элементе html.
На методы часто ссылаются как на то, что необходимо сделать (например, удалить узел):
document.getElementById(id) - получить элемент с указанным id из всего html
document.getElementsByTagName(имя) - получить все элементы с указанным названием (именем) тега из всего html
document.appendChild(узел) - вставить дочерний узел в html
document.removeChild(узел) - удалить дочерний узел из html
Формируют древовидную структуру ТОЛЬКО узлы-элементы-теги, текстовые узлы не могут в себе содержать другие узлы и строить дальше дерево!!!
Процесс формирования DOM происходит так: браузер получает HTML-код, парсит его и строит DOM.
Конечной целью является построения отображения этой страницы на экране. Т.е. по сути мы видим ДОМ в браузере.
Основные этапы работ, которые браузер выполняет для преобразования исходного кода HTML-документа в отображение стилизованной и интерактивной картинки на экране. Кстати, этот процесс называется «Критический путь рендеринга» Critical Rendering Path (CRP):
- Браузер получает HTML и парсит его, в итоге построит DOM. Так же происходит и с CSS файлом, он так же парсит его и образует CSSOM - объектная модель CSS. Он выглядит так же как DOM, но с соответствующими стилями для каждого узла.
- Когда сформировался DOM и CSSOM , происходит формирование дерева рендеринга (render tree) - это совокупность DOM и CSSOM.
Это дерево, которое даёт представление о том, что в конечном итоге будет отображено на странице. Это означает, что оно захватывает только видимый контент(элементы и текст) и не включает, например, элементы, которые были скрыты с помощью CSS-правила display: none.
Таким образом, render tree описывает визуальное представление DOM. - Далее браузер выполняет отрисовку render tree.
Для этого он:
—рассчитывает положение и размеры каждого элемента в render tree, этот шаг называется Layout;
Список свойств, изменение которых вызывает Layout:
width и height;
padding и margin;
display;
border;
top, left, right и bottom;
position;
font-size и другие.
—-выполняет рисование, этот шаг называется Paint.
Список свойств, изменение которых вызывают Paint:
color;
background;
visibility;
border-style и другие.
Что такое Лексическое Окружение? (окружение)
В JavaScript у каждой выполняемой функции, блока кода и скрипта ЕСТЬ связанный с ними внутренний (скрытый) ОБЪЕКТ, называемый лексическим окружением LexicalEnvironment.
Объект лексического окружения состоит из двух частей: объект и ссылка
1.Объект, в котором как свойства хранятся все локальные переменные
2.Ссылка на внешнее лексическое окружение – то есть то, которое соответствует коду снаружи (снаружи от текущих фигурных скобок).
Получается, работа с переменными(например переприсваивание) - это работа со свойствами этого объекта лексического окружения.
Переменные инициализируются тогда, когда до них доходит ВЫПОЛНЕНИЕ, те они записываются в объект, появляются в этом окружении.
Global Environment(глобальное окружение){
car: ‘bmw’, - запись переменной
sayHi: Function - запись функции
}
По-другому дела обстоят с функциями (Function Declaration) - инициализация происходит тогда, когда СОЗДАЕТСЯ лексическое окружение.
По этому такие функции могут вызываться раньше, чем мы объявили функцию.
При запуске функции для неё автоматически создаётся новое лексическое окружение, для хранения локальных переменных и параметров вызова.
У внутреннего лексического окружения есть ссылка - outer на внешнее, те когда код хочет получить доступ к переменной – сначала происходит поиск во внутреннем лексическом окружении, затем во внешнем, затем в следующем и так далее, до глобального.
Есть глобальное лексическое окружение, где записываются глобальные переменные, функции и тд. Если у такого окружения нет более глобального окружения, то он будет означать null, вместо объекта.
Отсюда можем понять, что если например, у функции в своем окружении не нашлось нужной переменной, то она ищем во внешнем окружении, если там нет, то поднимается еще выше. Если в итоге не нашлось, то будет ошибка.
Новое лексическое окружение функции создаётся каждый раз, когда функция выполняется.
И, если функция вызывается несколько раз, то для каждого вызова будет своё лексическое окружение, со своими, специфичными для этого вызова, локальными переменными и параметрами.
Function Expression - почему нельзя вызвать до ее инициализации? Потому, что в глобальном окружении она не записывается, как FD или переменные. По этому когда доходит до вызова такой функции, ее просто не существует пока что.
Пример1:
let name = “John”;
function sayHi() {
alert(“Hi, “ + name);
}
name = “Pete”; // (*) переприсвоилось значение
sayHi(); // Pete
//Функция получает текущее значение внешних переменных, то есть их ПОСЛЕДНЕЕ значение.
Пример2:
GlobalEnvironment{ counter: Function} - создалось глобальное окружение, куда записалась функция - FD. Такая запись { counter: Function} - это структура данных у окружения. Т.е. индетификатор - название переменной\функции, а значение - значение у примитива, а если функция, то Function.
const counter = ()=>{
// функция counter теперь может ссылаться на глобальное окружение в поисках необходимого:
counter =>GlobalEnvironment.
// При ВЫЗОВЕ функции counter создается ее лексическое окружение
let i=0
return () => { // возвращаем другую функцию
// так же ссылается на внешнее лекс. окружение - counter
//при вызове создается ее лексическое окружение
// тк в этой функции нет переменной i, то она ее найдет в функции counter и сохранится там измененное значение. При каждом вызове нашей возвращающейся функции, она будет выходить к окружению функции counter и брать оттуда переменную i.
console.log(++i)
}
}
const foo = counter() // здесь мы просто проинициализировали эту нашу функцию, которая вернулась из функции counter
foo() //1 // здесь мы вызываем нашу вернувшуюся функцию и в ней уже создается лекс. окружение.
foo() //2 // каждый раз при новом вызове этой функции создается новое лекс. окружение ее
foo() //3
Так же чтобы можно было отследить происходящие в лексическом окружении изменения, а также определить какое лексическое окружение является текущим, соответствующим данному этапу выполнения кода есть такое понятие как Контекст выполнения (execution context).
Первым контекстом выполнения, который создаётся при запуске JavaScript скрипта всегда является глобальный контекст выполнения (Global Execution Context). - глобальное окружение, глобальная область видимости.
Чтобы хранить и отслеживать контексты выполнения они формируются в стек контекстов выполнения (call stack) — список контекстов, организованных по принципу «последним пришёл — первым вышел».
Выполняемый контекст всегда является верхним элементом этого стека. После того, как необходимый код выполнится, связанный с ним контекст выполнения удалится, управление вернется в контекст, который находился элементом ниже, и теперь он будет верхним элементом — текущим контекстом выполнения.
Глобальная область видимости => Область видимости функции => Область видимости вложенной функции в предыдущую.
Зайдет последняя область и выйдет первой она же, когда выполнится и т.д.
Что такое замыкание?
Способность функции запомнить свое внешнее лексическое окружение.
Замыкание - это функция у которой есть доступ к своей внешней функции, даже после того, как внешняя функция прекратилась.
Это говорит о том, что замыкание может запоминать и получать доступ к переменным, и аргументам своей внешней функции, даже после того, как та прекратит выполнение, т.е. функция запоминает окружение свой внешней функции и может брать оттуда то, что необходимо.
При этом , когда внешняя функция отвыполнит уже свои действия, то ее окружение не уходит из памяти, тк в ее внутренней функции есть ссылка на это окружение.
Пример:
function getCounter() {
let counter = 0; // перезаписывается значение, тк окружение как было, так и осталось, в отличие от функции-замыкания - при новом вызове ее окружение формируется на новое.
return function() {
return counter++;
}
}
let count = getCounter(); // это замыкание, есть доступ к окружению внешней ее функции
console.log(count()); // 0
console.log(count()); // 1
console.log(count()); // 2
Мы храним анонимную внутреннюю функцию, возвращенную функцией getCounter в переменной count. Так как функция сount теперь замыкание, она может получать доступ к переменной counter в функции getCounter, даже после того, как та завершится.
Но обратите внимание, что значение counter не сбрасывается до 0 при каждом вызове count, как вроде бы она должна делать.
Так происходит, потому что при каждом вызове count(), создаётся новая область видимости, но есть только одна область видимости, созданная для getCounter, так как переменная counter объявлена в области видимости getCounter(), она увеличится при каждом вызове функции count, вместо того, чтобы сброситься до 0.
Примером замыкания можно назвать санку в thunk creator-е. Т.е. мы создаем thunk creator и вызываем его, в котором сидит сама санка. Санка же берет переданные данные из thunk creator-а. Таким образом получается замыкание.
Пример:
export const loginTC =
(data: any) => //это thunk creator
(dispatch: Dispatch<ActionsType>) => {
return data
}//сама санка, которая берет данные из thunk creator</ActionsType>
dispatch(loginTC(data))
Что такое рекурсия?
Рекурсия — это функция в своём теле вызывает саму себя.
Функцию, которая вызывает сама себя, называют рекурсивной функцией.
Вызов рекурсивной функции, называется рекурсивным вызовом.
Пример - Вычисление факториала с помощью рекурсии:
function f(n) {
if (n === 1){ // необходимо задать условия выхода из рекурсии, иначе она будет бесконечна
return 1;
}
return n * f(n - 1);
// 4f(4-1)
// 3f(3-1) = 6
// 2*f(2-1) = 2
//когда в if удовлетворится условие, то вернет число 1
}
f(4);
Теперь можем выполнить подсчет: возвращается 1 как результат выполнения этой функции f(2-1), соответственно, 21=2, затем это значение возвращаем как результат этой функции f(3-1), значит 32=6, и последнее - 4*6=18
Общее количество вложенных вызовов называют глубиной рекурсии.
Пример2:
function pow(x, n) {
// лексическая область видимости:
//1 шаг - {x: 2, n: 3}
//2шаг - {x: 2, n: 2}
//3шаг - {x: 2, n: 1}
if (n == 1) {
return x; //3 шаг - возврат 1 как результат предыдущего вызова функции pow
} else {
return x * pow(x, n - 1);
}
}
pow(2, 3) ;
//21 = 2
// 22 = 4
// 2*4 = 8
Для чего нужна самовызывающаяся функция?
(function () {
…..
}) ( )
Это функция, которая выполняется сразу же после того, как она была определена.
Одна из целей IIFE - ограничить область видимости. Сделать так, чтобы переменные, объявленные в ней, не убежали в глобальную видимость.
(function () {
var aName = “Barry”;
})();
// Variable name is not accessible from the outside scope
aName // throws “Uncaught ReferenceError: aName is not defined”
Главной идеей является то, что анонимная функция вызывается сразу после своего объявления. если нужно выполнить код один раз и сохранить его резульататы во “внешней среде” (без объявления глобальных переменных).
Мы не храним нигде ссылку на эту функцию. Нигде не храним возвращаемое значение. Так только функция инициализирована, она тут же вызывается.
Это может быть удобным вариантом инициализации, например, мы инициализируем и прикрепляем функции обработчиков событий один раз, после объявления функции вызываем ее, и теряем с ней связь.
Что такое инкапсуляция? ООП
Инкапсуляция - это один из принципов объектно-ориентированного программирования (ООП).
Отделение и сокрытие от внешнего мира внутренностей программы (переменных, функций, методов), называется инкапсуляцией.
Объект хранит свое состояние в приватном порядке, и только методы объекта имеют доступ для его изменения.
Если хотим изменить инкапсулированное состояние, мы не обращаемся к нему напрямую и не изменяем реквизиты некоторых объектов. Вместо этого вызываем метод объекта, и, возможно, объект ответит обновлением своего состояния.
Чем отличается интерпретатор и компилятор?
Простой интерпретатор анализирует и тут же выполняет программу построчно (покомандно), по мере поступления её исходного кода.
Недостаток - интерпретатору приходится проделывать одну и ту же работу, когда используете одинаковый код несколько раз.
Например, если вы находитесь в цикле, интерпретатор будет анализировать одни и те же строки снова и снова.
Также, такой интерпретатор обнаруживает ошибки в коде только при попытке выполнения строки с ошибкой. И никак не сможет сообщить об ошибке в коде с самого начала.
Компилятор не выполняет программу построчно, сначала, он последовательно анализирует и разбирает код программы, производит необходимую оптимизацию и только после этого генерирует машинный код, который впоследствии начнет выполняться.
Поэтому, при компиляции требуется больше времени для запуска, так как в начале должны пройти все её этапы. Но при этом компилятор оптимизирует код для увеличения скорости его работы. Например, циклы будут работать быстрее потому, что после оптимизации нет необходимости повторять одни и те же действия анализа кода для каждого прохода через цикл.
Также, компилятор сразу может сообщить, что в коде присутствует ошибка.
Как сейчас работает движок Js?
Сначала исходный код программы последовательно анализируется и разбирается компилятором. Первым традиционным этапом работы стандартного компилятора является лексический анализ исходного кода. На этом этапе каждая строка кода посимвольно анализируется и разбивается на значимые для языка части. Эти имеющие смысл для языка части называются лексемами.
var a = 2;
Эта программа, вполне вероятно, будет разбита на следующие лексемы:
var — объявление переменной,
a — идентификатор (имя) переменной,
= — оператор присваивания,
2 — число,
; — конец инструкции
Что такое контекст выполнения? (лексическая область видимости, окружение)
Чтобы можно было отследить происходящие в лексическом окружении изменения, а также определить какое лексическое окружение является текущим, соответствующим данному этапу выполнения кода есть такое понятие как Контекст выполнения (execution context).
Первым контекстом выполнения, который создаётся при запуске JavaScript скрипта всегда является глобальный контекст выполнения (Global Execution Context). - глобальное окружение, глобальная область видимости.
Чтобы хранить и отслеживать контексты выполнения они формируются в стек контекстов выполнения (call stack) — список контекстов, организованных по принципу «последним пришёл — первым вышел».
Выполняемый контекст всегда является верхним элементом этого стека. После того, как необходимый код выполнится, связанный с ним контекст выполнения удалится, управление вернется в контекст, который находился элементом ниже, и теперь он будет верхним элементом — текущим контекстом выполнения.
Глобальная область видимости => Область видимости функции => Область видимости вложенной функции в предыдущую.
Зайдет последняя область и выйдет первой она же, когда выполнится и т.д.
Что такое каррирование?
Это процесс, когда можно трансформировать функцию с несколькими аргументами в функцию, которая будет возвращать последовательность других функций, которые вложены друг в друга, соответственно, каждая такая функция будет последовательно принимать в параметр переданный аргумент.
Пример:
обычная функция:
function volume(l,w,h) {
return l * w * h;
}
const aCylinder = volume(100,20,90) // 180000l
каррирование:
function volume(l) {
return (w) => {
return (h) => {
return l * w * h
}
}
}
const aCylinder = volume(100)(20)(90) // 180000
Суть в том, что самая последняя вложенная возвращаемая функция имеет доступ к окружению предыдущих функций
Отличие proto от prototype?
Это свойства объекта.
У всех объектов(объект, массив, number, string, boolean(помним, что если поставить точку, то создается обертка, которая на время создает объект), функция, функ. выражение, стрелочная функция, класс(это навороченная функция, а значит объект)) есть proto.
proto - это объект. proto, относящиеся к одному типу объектов, равны, т.к. они относятся к одному и тому же объекту proto, если разные типы, то не равны:
- {}.proto === {}.proto // true, т.к. один тип
- proto всех видов функций(даже класс), будут так же равны
- function add.proto === const a = ()=>{}.proto // true, т.к. один тип
- {}.proto === function add.proto
// false , т.к. разные типы
Prototype - независимый объект, у которого есть свои свойства и методы(т.е. это те, от кого все пошло)(сlass String{}, class Samurai{}, function First(){}(функции-конструкторы)).
Он есть только у КЛАССА и ФУНКЦИИ-КОНСТРУТОРА.
proto ссылается на прототип(prototype) того класса, с помощью которого был создан экземпляр:
1. сonst a = new String(‘aaa’)//экземпляр класса
a.proto === String.prototype // true
//__proto__ указывает на прототип String.prototype по этому true
- сlass YouTube{} === Function.prototype // true, т.к. создан с помощью new Function()
- class Samurai{ }//класс
const s = new Samurai()//экземпляр класса
s.proto === Samurai.prototype // true - Array.proto === Function.prototype
// true, тк все классы - это функции
//здесь берется подкапотный new Array() - class User{ }
User.proto === Function.prototype
User.proto.proto === Object.prototype
User.proto.proto .proto===null
//User создается с помощью new Function
//второе .proto будет относится уже к Function.prototype, а создался он с помощью new Object
//третье .proto относится уже к Object.prototype, а его proto уже никуда не ссылается, т.к. это объект
Зачем эти прото и прототип?
let dim = {name: Dim}
dim.toString()// у объекта нет такого методы, и под капотом происходит это:
dim.proto => Object.prototype =>{toString(){ }}
// смотрит на что ссылается прото, лезет в него(Object) и если в этом объекте сидит этот метод, то берет его.
Какие области видимости бывают?
Но не все переменные в нашем коде одинаково доступны. Доступна ли переменная и как получить к ней доступ, определяют области видимости.
Область видимости — это часть программы, в которой мы можем обратиться к переменной, функции или объекту. Этой частью может быть функция, блок или вся программа в целом — то есть мы всегда находимся как минимум в одной области видимости.
1.Глобальная область видимости — это самая внешняя коробка из всех. Когда мы «просто объявляем переменную», вне функций, вне модулей, то эта переменная попадает в глобальную область видимости.
2.Блочная область видимости ограничена программным блоком, обозначенным при помощи { и }. Например, if или switch
3.Функциональная область видимости — это область видимости в пределах тела функции.
- Модульная область видимости - импорт\экспорт переменных между файлами. Модуль - это файлы. Переменные, объявленные в этом модуле будут доступны только там, если же их импортируют в другой модуль, то они будут доступны в этом модуле.
Поведение, когда переменные родительских областей становятся доступны в дочерних, называется лексической областью видимости.
Кстати, var не имеет блочной области видимости, например, объявленная в if, к ней будет доступ и за пределами if. В функции она имеет область видимость, как и остальные.
Есть ли this в стрелочных функциях?
В стрелочных функциях this устроен иначе.
Если в обычной функции решающим является момент вызова, то в стрелочной функции — момент создания.
Еще можно сформулировать так — в стрелочных функциях this сохраняет значение this окружающего контекста в момент создания.
class Dog {
constructor(name){
this.name = name; // здесь будет сидеть ‘Bim’
}
eat(food){
console.log(‘method’, this)
// выведет в консоль Dog {name: Bim}
food.forEach((item) => {
console.log(‘arrow func’, this)
// выведет в консоль Dog {name: Bim}, это доказывается, что у стрелочной функции нет своей this и она его берет из внешнего контекста
console.log(${this.name} is eating ${item}
)
});
}
}
const bim = new Dog(‘Bim’); // создаем новый объект Dog
bim.eat([‘bone’, ‘cookie’])
Что такое Виртуальный Дом?
Виртуальный объект DOM — облегченная копия Реального Дома.
Виртуальный объект DOM имеет те же свойства, что и реальный объект DOM, но у него нет реальной возможности напрямую изменять то, что отображается на экране. По этому и называется легковесной копией.
Т.е. у него есть свойства, как у Реального Дома - свойства часто ссылаются как на то, С ЧЕМ необходимо что-либо сделать (например, название узла). document.innerHTML - отобразит текст, который содержится в элементе html.
Но нет методов, т.е. он не может что-то сделать с элементом:
На методы часто ссылаются как на ТО, что необходимо сделать (например, удалить узел):
document.getElementById(id) - получить элемент с указанным id из всего html
Зачем нужен PATCH, если есть PUT?
PUT подразумевает под собой, что мы отправим полностью объект, который сидит на серваке, но где-то с необходимыми обновленными свойствами
PATCH - отправит только те свойства, которые хотим изменить.
Плюс PATCH в том, чтобы не происходило конфликтов. Например, один человек изменил свойство в объекте и отправил через PUT , через секунду другой человек отправляет объект с измененным другим свойством, но в этом объекте по-прежнему сидит то старое свойство, которое изменил первый человек. В результате это старое свойство снова появляется на сервере. С PATCH мы точечно меняем свойства.
Как образуется обычный DOM из HTML-страницы?
DOM имеет древовидную структуру, состоящую из ДОМ-узлов.
Браузер получает HTML-файл, парсит его и вызывая document.createElement для каждого узла в DOM. Дом будет состоять из Дом-элементов - это объекты-узлы . Далее можно будет работать с ним, применяя, например, const el = document.getElementById(‘div’) и уже что-то с этим элементом делая, например,
el.innerHTML=’HELLO!!!’, сразу же эти изменения фиксируются в DOM и HTML-страница перерисовывается.
Виртуальный Дом уже относится к Реакту, не касаясь обычного HTML-я.
document.querySelector, зачем он нужен?
Это метод для объекта document, позволяющий найти HTML-элемент с помощью CSS-селекторов:
document.querySelector(‘.name’)
// найдет первый попавшийся HTML-элемент, который содержит этот класс
С полученным элементом можно будет производить различные манипуляции: менять его текст, атрибуты, CSS стили
Если совпадений не найдено, то возвращается значение null.
Не допускается использование CSS псевдоэлементов, вернет так же null.
Если необходимо найти несколько, то .querySelectorAll вернет массив из этих элементов.
Что такое промис? Какие состояния бывают у промиса? Какие статические методы бывают у промиса? Какие методы бывают у промиса?
Это объект, который используется для написания и обработки асинхронного кода.
Выполняемые внутри промиса функции возвращает промис-обещание. Внутри этого промиса хранится какой-то результат из этой функции.
Промис может находиться в одном из трёх состояний:
pending — стартовое состояние, операция стартовала;
fulfilled — получен результат;
rejected — ошибка.
У промиса есть 3 метода then(), catch() и finally(), которые позволяют использовать результат вычисления функции, которые содержатся в промисе.
С помощью then() мы подписываемся на момент, когда промис зарезолвится(resolve).
Таким образом, функция-коллбэк, которую передали в .then, вызывается, и в этот колбэк передаются данные, которыми зарезолвился промис. then() всегда возвращает НОВЫЙ промис.
const promis = axios.get(‘……….’)
promis.then((data)=>{выполнится, когда промис зарезолвился})
Пишем более кратко:
axios.get(‘……….’).then((data)=>{выполнится, когда промис зарезолвился})
С помощью catch обрабатываем ошибку, если она произошла:
axios.get(‘……….’)
.then((data)=>{выполнится, когда промис зарезолвился})
.catch(error=>{выполнится, когда промис зареджектится})
finally() выполнится в любом случае, независимо от того была ли ошибка или нет:
axios.get(‘……….’)
.then((data)=>{выполнится, когда промис зарезолвился})
.catch(error=>{выполнится, когда промис зареджектится})
.finally(()=>{выполнится не зависимо от того, что произойдет})
Все те промисы, которые приходят, они созданы с помощью класса Promise через
new Promise(()=>{….}) -создается экземпляр класса
У самого класса Promise есть так называемые статические методы, которые относятся только к нему, а then(), catch() и finally() - относятся к экземплярам. Вот эти статические методы:
- Promise.all:
если нам нужно запустить множество промисов параллельно и дождаться, пока все они выполнятся.
Принимает массив промисов и возвращает новый промис тогда, когда эти все промисы зарезолвятся.
Результатом промиса будет массив из результатов каждого промиса.
Promise.all([
new Promise(resolve => setTimeout(() => resolve(1), 3000)), // 1
new Promise(resolve => setTimeout(() => resolve(2), 2000)), // 2
new Promise(resolve => setTimeout(() => resolve(3), 1000)) // 3
]).then(alert); // когда все промисы выполнятся, результат будет 1,2,3, но .then() так же вернет новый промис с этим результатом.
// каждый промис даёт элемент массива.
Результат будет в такой же последовательности, как и промисы вне зависимости от того, кто быстрее зарезолвился.
Если хоть в каком-то промисе произошла ошибка, то итоговый промис никогда уже не зарезолвится. Будет ошибка. - Есть метод Promise.allSettled, который помогает обработать промис даже если в каких-то промисах произошла ошибка. Результат будет таким:
[ // приходит уже не просто массив, а массив объектов, где лежат инфо о каждом промисе. Если он зарезолвился, то в value сидит ответ, если нет - то ошибка сидит.
{status: ‘fulfilled’, value: …объект ответа…},
{status: ‘fulfilled’, value: …объект ответа…},
{status: ‘rejected’, reason: …объект ошибки…}
] // по этому обрабатывать нужно как объект, а не массив: Promise.allSettled(…).then(result=>result.value)
Как бы отчет по каждому промису.
В старых браузерах не поддерживается, нужен полифил.
- Метод Promise.resolved([1,2,3])
Вернет сразу зарезолвенный промис, например, может понадобиться, когда нужна заглушка, и хотим симитировать получение данных с сервера, но бэк еще не готов. Просто создаем такой промис и вставляем нужные нам данные. И далее уже можем обрабатывать с помощью .then() этот промис. - Метод Promise.reject({message: ‘Some error’})
Cоздаем промис ошибкой. Возвращает зарежектнутый промис, который можем обрабатывать .catch() - Метод Promise.race([…, …., ….]):
Принимает массив промисов, ждёт только ПЕРВЫЙ выполненный промис, из которого берёт результат или ошибку. После этого остальные промисы игнорируются. - Метод Promise.any([…, …., ….]):
Принимает массив промисов, ждёт только ПЕРВЫЙ УСПЕШНО выполненный промис, из которого берёт результат.
Если первый был с ошибкой, то берется следующий, если он успешен и т.д.
Если отклонились все промисы, то возвращённый объект Promise будет отклонён с помощью AggregateError – специального объекта ошибок, который хранит все ошибки промисов в своём свойстве errors.
———————————————————————–
Есть простой синтаксический сахар - asinc/await, который используется ВМЕСТО .then().
сonst promis = await axios.get(‘получим с сервера юзера под id2’)//await возвращает результат зарезолвенного промиса
console.log(promis ) // {name:’Vasya’}
// в переменной promis будет результат зарезолвенного промиса с помощью await БЕЗ использования метода .then().То есть результат res внутри .then((res)=>console.log(res)) === результату в переменной, где применяется await. ( then((res)=>///) - res- здесь будет результат зарезолвенного промиса )
Если переменные с await-ом стоят друг за другом, то остальные после первого будут дожидаться пока первый выполнится и т.д.:
const foo = async ()=>{
const pr1= await fetch(‘……..’) // выполняется…
const pr2= await fetch(‘……..’)// ждет пока 1й вып.
const pr3= await fetch(‘……..’)// ждет пока 2й вып.
}
Эти переменные можно использовать, например засетать :
const [user, setUser] = useState()
setUser(pr1.user)
Если один из запросов с ошибкой, то следующие прерываются и ловятся ошибкой.
В async функции можно использовать try\catch\finally:
const foo = async ()=>{
try{
const pr1= await fetch(‘……..’) // выполняется…
const pr2= await fetch(‘……..’)// ждет пока 1й вып.
const pr3= await fetch(‘……..’)// ждет пока 2й вып.
} catch(err){
console.log(‘‘ERROR’’, err)
}
}
await обязательно должен быть в связке с async, по этому не забываем ставить async перед функцией.
Если после await следует ниже код, то он не будет выполнятся, если не выполнится await
const pr1= await fetch(‘……..’)
сonsole.log(‘Hello!’)
Это тоже самое, если бы мы писали с .then():
fetch(‘……..’).then(сonsole.log(‘Hello!’))
//если fetch не зарезолвится, то и .then не выполнится
Если же мы берем данные, которые фиксированные, а не промис и пропускаем через await, то они так же поместятся в переменную, как поместился бы и промис зарезолвенный:
const api={
save(){},
read(){
return {name: ‘Alex’}
//здесь обычный объект, не промис
}
async function give(){
await api.save()
let data = await api.read()
// эвэйтим просто данные, не промис, но в итоге в //переменную все равно записываются данные - //{name: ‘Alex’}
console.log(data)
}
give()
Эвэйтить можно заранее, например, если в будущем планируется модификация объекта, где вместо этих данных будет промис, таким образом, можем заранее предугадать, чтобы потом не переписывать код.
Как сделать промисификацию:
const api={
save(){},
async read(){ //сделать функцию ассинхронной, любая ассинх.функция возвращает промис.
return {name: ‘Alex’}
//либо вместо async написать new Promis(resolve=>resolve({name: ‘Alex’}))
//либо Promis.resolve({name: ‘Alex’})
}
async function give(){
await api.save()
let data = await api.read()
// эвэйтим просто данные, не промис, но в итоге в //переменную все равно записываются данные - //{name: ‘Alex’}
console.log(data)
}
give()