JavaScript — это «синхронный однопоточный язык
Вы это где-то читали, и что это значит? Просто продолжайте читать, и вы узнаете это по ходу дела.
Я начал программировать, создавать небольшие проекты и часто думал: что происходит, когда я запускаю код? Как работает JS? Что за волшебство происходит на заднем плане?
Сегодня давайте разберемся, как работает js. Я дам простое объяснение из своих ограниченных знаний.
Допустим, вы написали небольшую программу — объявили переменные, создали fn и т. д. и запускаете ее через браузер. Итак, откуда браузер знает JS? Как он может запустить ваш код?
Что ж, хорошо, что каждый основной браузер имеет свой собственный движок JS.
Зачем им движок JS? Большинство веб-сайтов так или иначе используют JS, и браузеру нужно для взаимодействия и эффективного запуска JS на веб-странице. Отсюда и JS-движок.
Хорошо, какой движок JS используют браузеры? Большинство браузеров разработали собственный движок JS. В Chrome используется движок V8, созданный Google, в Firefox — Spidermonkey, в Safari — Nitro и т. д.
Теперь вы знаете, почему одни браузеры работают хорошо, а другие нет.
Теперь, когда это сказано, давайте вернемся к запуску нашего кода.
Скажем, у нас есть небольшой код:
var a = 2; var b = 4;
function add() { var ans = a + b; return ans; } add();
Когда мы запускаем это, контекст выполнения (глобальный контекст) создается JS в качестве первого шага перед выполнением кода. Думайте об этом как о большой коробке. Вот где все в JS происходит.
Теперь этот контекст выполнения передается в так называемый стек вызовов, где происходит основное выполнение. Помните об этом. Думайте о стеке вызовов как о таблице, в которой мы храним файлы поверх других.
Теперь мы знаем, что глобальный контекст создается при запуске кода, и этот глобальный контекст передается в стек вызовов для выполнения.
Теперь давайте посмотрим, что происходит внутри глобального контекста.
Глобальный контекст создается в два этапа:
1) Компонент памяти — здесь хранятся все переменные и функции в видеkey : value
пар. Ключ может быть переменной, а значением является его текущее значение.
Здесь, на первом этапе, переменная «a» будет храниться как «неопределенная». Это хранится в компоненте памяти как a : undefined
Здесь значения для этих переменных не присваиваются компонентом «Память». Это происходит на следующем этапе. Пока переменные назначаются как undefined
, а для функций добавляется вся функция целиком.
2) Компонент кода — здесь происходит выполнение каждой строки кода. На этом этапе значения присваиваются переменным.
Теперь значение a
становится 2
из undefined
и будет храниться как- a : 2
JS выполняет код по одной строке за раз. JS не может выполнять задачи более чем по одной за раз. Итак, вот что значит однопоточность.
JS выполняет код в определенном порядке. Выполняется первая строка, и только после ее завершения переходит к следующей строке. Он не может перейти на 3-ю строку до выполнения 2-й строки. Это называется синхронным.
Вот и все — «синхронный однопоточный».
Теперь, когда он встречает функцию, новый контекст выполнения, подобный первому, создается внутри первого контекста выполнения с теми же двумя фазами и той же процедурой.
Теперь в тот же момент этот новый контекст выполнения передается в наш стек вызовов. То есть новая коробка хранится поверх другой коробки, которая стоит на столе.
Теперь наш стек вызовов имеет первый контекст выполнения внизу, а поверх него передается этот новый контекст выполнения. JS пытается быстро выполнить все, что попадает в стек вызовов, ничего не ожидая. После выполнения этот новый контекст выполнения удаляется, а также извлекается из стека вызовов. Это происходит каждый раз, когда функция встречается внутри кода.
Теперь, когда функции выполнены, он переходит к следующей строке, и, наконец, первый глобальный контекст выполнения также удаляется и выталкивается из стека вызовов. Следовательно, стек вызовов также становится пустым.
Хорошо, давайте посмотрим на это: Что произошло бы, если бы в глобальном контексте выполнения было две функции? Да, вы правильно догадались.
Будут созданы два новых контекста выполнения, которые сделают то же самое, что описано выше. Но помните, он не формирует вместе два новых контекста выполнения, а сначала завершает первую функцию и удаляет ее. И только потом переходит к следующей функции.
Простой не так ли?
Теперь подумайте об этом. Что, если есть функция внутри функции? Я думаю, вы тоже это поняли.
В этом случае будет 3 контекста выполнения, и эти 3 также будут переданы в стек вызовов. Контекст выполнения третьей функции будет в верхней части стека вызовов, а две другие — в нижней. и поверх этого находится основная функция, а третья будет функцией внутри этой основной функции.
И затем после выполнения каждый из них будет удаляться один за другим, сначала выполняется верхний контекст выполнения, а затем удаляется из стека вызовов, затем выполняется следующий и удаляется из стека вызовов, и так повторяется до тех пор, пока не Стек вызовов становится пустым.
Вот как работает код внутри JS. Я попытался объяснить это как можно лучше.
Спасибо за чтение!