JavaScript и« Java - совершенно разные языки, как по концепции, так и по дизайну».

JavaScript - это высокоуровневый, часто компилируемый точно в срок и мультипарадигмальный язык программирования.

точно в срок - код компилируется тогда, когда это необходимо, а не до выполнения.

мультипарадигма - javaScript поддерживает как объектно-ориентированное программирование с прототипным наследованием, так и функциональное программирование.

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

Но в отличие от других языков программирования, javascript однопоточный. Это означает, что выполнение кода в js выполняется последовательно, что означает, что мы можем столкнуться с тем, что один фрагмент кода блокирует другой фрагмент кода.

Когда вы посещаете сайт в своем браузере, начинает работать единственный поток выполнения javascript. Этот поток отвечает за обработку всего, например прокрутки, прослушивания событий DOM, таких как щелчки мыши, печати веб-страницы. Когда это единственное выполнение заблокировано, веб-страница перестает отвечать.

Так как же с этим справляется javascript?

когда происходит асинхронное событие (например, щелчок мышью, срабатывание таймера или завершение XMLHttpRequest), оно ставится в очередь для выполнения позже…. После того, как начальный блок JavaScript завершает выполнение, браузер сразу же задает вопрос: что ожидает выполнения? Затем браузер выбирает один и немедленно выполняет его. Остальные будут ждать до следующего возможного раза, чтобы выполнить.

Для понимания это позволяет сначала понять время выполнения javascript.

Стек вызовов - область памяти, работающая в режиме FIFO. Когда компьютерная программа запускает новый поток, создается новый стек. Движок Js начинает подталкивать функции для выполнения в стеке вызовов, начиная с родительской функции.

Когда функция возвращает значение или вызывает веб-API, она извлекается из стека и переходит к следующей функции в стеке. Этот процесс синтаксического анализа функции и извлечения ее из стека - вот что они имеют в виду, когда говорят, что Javascript выполняется синхронно. Он выполняет одно действие в одном потоке.

Например

function main(){  //3  
average()         //2
}
function average(){
add()             //1
}
main()

функция выполняется в порядке 1- ›2-› 3

Куча -

Здесь движок V8 хранит объекты или динамические данные. Это самый большой блок области памяти, и именно здесь происходит Сборка мусора (GC).

Стеки против кучи

  • Каждый вызов функции добавляется в стек.
  • Все локальные переменные, включая аргументы и возвращаемое значение, сохраняются в блоке кадра функции в стеке.
  • Все примитивные типы, такие как int и string, хранятся непосредственно в стеке. Это относится и к глобальной области видимости, и да, String - это примитивный тип в JavaScript.
  • Все типы объектов создаются в куче, и на них ссылаются из стека с помощью указателей стека. Функции - это просто объекты в JavaScript. Это относится и к глобальной области видимости.
  • Функции, вызываемые из текущей функции, помещаются в верхнюю часть стека.
  • Когда функция возвращает, ее кадр удаляется из стека.
  • После завершения основного процесса объекты в куче больше не имеют указателей из стека и становятся бесхозными.
  • Если вы не сделаете копию явно, все ссылки на объекты внутри других объектов выполняются с использованием ссылочных указателей.

Поскольку JavaScript является однопоточным, у него только один стек и одна куча. Следовательно, если какая-либо другая программа хочет выполнить что-то вроде HTTP-запроса, она должна дождаться полного выполнения предыдущей программы. Это действительно плохо для любого языка программирования. Упс

Здесь вступают в действие цикл событий и очереди обратного вызова.

Итак, что происходит на самом деле

В браузере постоянно происходит множество вещей, таких как HTTP-вызовы, события щелчка мыши, задержка выполнения с использованием функции setTimeOut () и множество прокрутки ... представьте, что все эти задачи выполняются одним потоком, не ухудшит ли это взаимодействие с пользователем

Итак, что делает браузер, так это то, что он использует язык низкого уровня, такой как C++, для выполнения этих операций и предоставляет чистый асинхронный JavaScript API для работы. Эти API-интерфейсы известны как веб-API.

Давайте разберемся с асинхронным поведением с помощью кода.

function main(){  
average()         
}
function average(){       //2
add()             
}
function add(){                      //3
setTimeout(callback,3000)             //4
}
main()              //1

В стеке вызовов, как передаются функции

1 →2 →3 →4

4 содержит вызов веб-API, поэтому он передается веб-API с функцией обратного вызова и извлекается из стека. Затем выполняются и извлекаются 3 - ›2-› 1.

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

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

Цикл обработки событий отправляет в стек по одной функции обратного вызова, когда стек пуст. Позже стек выполнит функцию обратного вызова.

Заключение

Вот как javascript обрабатывает выполнение задачи в браузере. Node js - это среда выполнения javascript, в которой используется механизм Google V8. Но Nodejs полагается не только на свой цикл обработки событий. Он использует библиотеку libuv, написанную на языке c, для работы вместе с циклом обработки событий V8 для расширения того, что можно делать в фоновом режиме.

NodeJS имеет цикл событий и может выгружать задачи в свой пул внутренних потоков или ядро, чтобы выполнять код, пока он ожидает ввода-вывода, что позволяет NodeJS обрабатывать множество запросов одновременно, даже если он является однопоточным.