JavaScript — это однопоточный, неблокирующий, асинхронный, параллельный язык. Ну и что? Какое мне дело до всех этих терминов?

Давайте объясним цикл событий, и в конце мы поговорим о типе данных,

Однопоточный:

Подумайте о ресторане, который называется JavaScript. Предположим, вы сидите за столиком и ждете, пока официант примет у вас заказ. Через некоторое время официант принимает у вас заказ и идет на кухню, велит повару подать ваш заказ. И официант подходит к другому столику и принимает заказ от клиента.

Этот официант выполняет задачу по приему заказа от клиента. Если в этом отеле есть только один официант, то в контексте JavaScript он называется однопоточным, потому что один поток или официант выполняет задачу по приему заказа. Если есть много ожидающих или потоков, это называется многопоточным. Но JavaScript использует один поток для выполнения всех задач.

Одновременно:

Это означает одну вещь за раз, не более одной. Итак, в JavaScript-отеле, если много клиентов ждут еды, используется один поток для приема заказов, тогда термин «Concurrent» говорит, что этот поток или официант принимает по одному заказу за раз от клиента не более чем от одного . Это означает, что один поток используется для выполнения только одной задачи, такой как выполнение функции или другой вещи, за раз, а не для многих операций.

Неблокирующий:

Что подразумевается под блокировкой? Блокирующие средства, которые создают блокировку, что еще более того. Неблокирующие средства, которые ничего не блокируют.

Наше путешествие в отеле JavaScript продолжилось…

Сценарий 1:

Если вы дойдете до этого момента, вы заметите проблему с официантом (один поток) в отеле. Если официант принимает заказ от вас как от клиента, идите на кухню, чтобы сказать повару, что он приготовил для вас заказ. А официант ждет, пока ваша еда будет готова к подаче. И он ждет, ждет и ждет.

Если это так, то другой клиент может никогда не прийти в отель, потому что официант слишком занят моим заказом, чтобы его выполнить, поэтому другие клиенты, ожидающие выполнения заказа, игнорируются.

Сценарий 2:

Но в нашей реальной жизни этого не происходит. Официант не ждет приготовленную еду на кухне, а говорит повару приготовить еду к подаче, а сам в это время собирает другие заказы. Эти заказы ставятся в очередь один за другим, и когда еда и все заказы принимаются, официант обслуживает заказ. И дальше собирать заказ.

По поведению официанта можно сказать, что он не блокирует выполнение приема заказа, пока другая задача обрабатывается позади. Этот официант или однопоточный выполняет каждую задачу, которая выполняется синхронно, например, подача готовой еды, и ставит задачу за очередь обратного вызова, например, приготовление новой еды на кухне, что в основном является асинхронной задачей. Такой характер выполнения называется неблокирующим.

Синхронный против асинхронного:

Синхронный означает последовательное выполнение кода. Синхронный код ожидает выполнения предыдущего оператора (сценарий 1 сверху). Асинхронность означает, что выполнение кода следующего оператора не останавливается для выполнения предыдущего оператора (сценарий 2 сверху).

Стек вызовов:

Если вы знакомы со структурой данных Stack, вы уже босс. Но если ты не такой, то это фото для тебя.

На этой фотографии, если вы поместите E поверх D и сформируется левый стек (это операция добавления чего-то в стек). Когда мы хотим удалить что-то из стека, это называется операцией pop. В правом боковом стеке убираем E.

Нам снова нужно вернуться к нашему JavaScript-отелю.

Сценарий 3:

Теперь снова представьте себе официанта, стоящего перед вами с блокнотом в руке в отеле. Вы говорите два бирияни (асинхронный вызов, потому что официант не может подать это сразу). Официант вербует 2 бирияни в свой блокнот. Затем идите на кухню, сообщите повару о приготовлении 2 бирияни и не ждите на кухне, а также не пролистывайте заказ в нодпаде (свяжите это с получением запроса от сервера или функцией setTimeout)

Сценарий 4:

Официант подходит к другому клиенту, и официанта просят подать бургер (который уже готов). Официант регистрирует заказ в своем блокноте. Затем немедленно подайте этому клиенту бургер из отображаемой готовой еды (синхронный вызов). Наконец, вычеркните заказ, когда он будет подан. (Свяжите это с console.log(2)).

Список заказов от клиентов в нодпаде похож на зачисление задачи для выполнения в стек вызовов в JavaScript.

Цикл событий:

Если это синхронный вызов, он помещает задачу в стек и выполняет ее. Наконец извлеките задачу из стека. Если это асинхронный вызов, он подталкивает его к задаче. Задача передается в веб-API и извлекается из стека. Выполнение задачи завершается в веб-API и переходит в очередь обратного вызова и ждет, пока стек не будет очищен. Когда все синхронные вызовы выполняются и стек очищается, очереди обратного вызова помещаются в стек и выполняются. Выполнение этих асинхронных обратных вызовов является циклом событий.

Пример:

Посмотрите на эту анимацию…

Эта анимация выполняет следующий код.

console.log() — это синхронный вызов (как в сценарии 3 выше), а setTimeout — асинхронный вызов (как в сценарии 4 выше).

Во-первых, console.log(‘Hi’) выталкивается из стека, выполняет ‘Hi’ на консоли и извлекается из стека. Затем setTimeout помещается в стек и передается его действие для завершения в веб-API. И setTimeout извлекается из стека. console.log(‘Bye’) выталкивается из стека, выполняет ‘Bye’ на консоли и извлекается из стека.

Но негласно, когда задача setTimeout в веб-апи выполнена, он переносится в очередь обратного вызова и ждет очистки стека вызовов. Когда все синхронные задачи выполнены, задачи из очереди обратного вызова помещаются в задачу. В нашем случае console.log(‘cb1’) помещается в стек, а ‘cb1’ печатается на консоли, а console.log(‘cb1’) извлекается из стека.

Но, наконец, после всей этой ерунды вы получаете свои 2 бирияни на стол. Один бирияни для вас. Но другие??? кто знает !!!

Типы данных:

В JavaScript есть два типа данных. Один примитивный тип, а другой ссылочный тип.

Примитивные типы: undefined, null, логические значения, числа, строки, символы, BigInts. Ссылочными типами являются объект, массив и функция.

Когда мы присваиваем значение переменной примитивного типа, мы можем получить к ней доступ по самому ее значению. Когда мы присваиваем значение переменной ссылочного типа, мы можем получить к ней доступ по ее ссылке.

Подъем:

Во время синтаксического анализа документа JavaScript перед выполнением кода объявления переменных и функций выводятся наверх. Это известно как подъем.

переменная имени выполняется в блоке else и вне блока if-else из-за подъема. А код под капотом на самом деле выглядит так.

Посмотрите внимательно. объявление имени поднимается, но не его значение. Вот почему имя «Амир» в блоке if и не определено в блоке else и вне блока if-else.

Отдых против оператора спреда:

Оператор Rest собирает все данные, которые необходимо повторить, в виде массива, а оператор распространения распространяет все данные в том месте, где требуется более одного аргумента.

Пример оператора спреда:

Пример оператора отдыха:

Кроссбраузерное тестирование:

Почему это важно?

  1. Разные браузеры имеют разные технологические особенности отображения вещей по-разному. Пользователь может использовать любой браузер по своему усмотрению в контексте популярных браузеров.
  2. Разные устройства отображают один и тот же пользовательский интерфейс по-разному с точки зрения размера и других параметров.
  3. Люди с ограниченными возможностями могут использовать конечный продукт, могут обычно не использовать мышь или иногда использовать только клавиатуру.

Рабочие процессы для кроссбраузерного тестирования:

  1. Первоначальное планирование:

Перед началом процесса разработки разработчику необходимо уточнить, какие функции есть у веб-сайтов, функциональность, сроки проекта, сумма к оплате и так далее.

2. Разработка:

На этом этапе разработчик может действовать в зависимости от ситуации и разрабатывать все это не сразу, а по частям.

3. Тестирование:

После каждой реализации разработчик должен протестировать ее в определяющей области контекста проекта.

4. Исправления/итерация:

Если ошибка обнаружена на этапе тестирования, разработчик должен исправить код и выполнить итерацию того же кода.

Подводя итог, после первоначального планирования необходимо повторно выполнить последние 3 шага для получения наилучшего результата.