Контекст выполнения, стек выполнения, цикл событий, очередь задач и среда выполнения являются наиболее важными основами JS, но, к сожалению, большинство из нас не понимают этих концепций. В последнее время я работаю над этими принципами, и вот опыт и знания, которые я приобрел ...

Вступление:

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

В этой истории я попытаюсь обсудить эти ключевые компоненты языка программирования JS, а именно:

  • Контекст исполнения.
  • Стек выполнения.
  • Веб-API или среда выполнения узла (или понимание любой среды выполнения).
  • Очередь задач.
  • Цикл событий.

Предварительные требования:

Прежде чем переходить к деталям, вам важно понять однопоточную и синхронную природу JS и то, как возможно асинхронное выполнение - я рассмотрел это в https://medium.com/@pravngaur/unthreading-asynchronous -js-39fdf57486ec .

Пожалуйста, прочтите его, прежде чем продолжить рассказ.

1) Контекст выполнения:

Механизм JS (V8 для chrome, SpiderMonkey для Mozilla) инициализирует контекст выполнения для каждого вызова метода. Execution-Context можно понимать как объект-оболочку, который содержит ключевые детали для обработки данного метода.

Контекст выполнения содержит 3 ключевых компонента:

a) Объект переменных (VO): это родительский объект, который содержит все переменные (это может быть числовое / строковое значение, объект JS или другая функция, объявленная в этой функции), инициализированные внутри этого метод и полученные аргументы.

b) Scope Chain: для этого нам сначала нужно понять, как scoping работает в JS.

JS следует лексической области видимости, то есть функции, переменные и объекты, объявленные внутри {}, доступны в пределах / конце блока, то есть "}".

var scopingExample = "Scoping sample string";
function testScopingConcept(){
 var scopingExample = "This is a new string";
 console.log(scopingExample);//prints: This is a new string
}
testScopingConcept();
console.log(scopingExample);//prints: Scoping sample string

Если вы запустите приведенный выше код в консоли браузера, вы получите следующий результат:

This is a new string
Scoping sample string

«Это новая строка» печатается из testScopingConcept function, потому что у нее есть собственная независимая область видимости & scopingExample variable объявлена ​​в глобальной области видимости и также в области этой функции. Итак, локальное объявление имеет приоритет. Помните, что лексическая область видимости определяется открывающими и закрывающими фигурными скобками: {}.

Глобальная область действия: это область действия верхнего уровня, которую мы, как разработчики, не создаем. Когда мы пишем любой JS-код, мы не начинаем с {, а просто продолжаем и начинаем объявлять переменные / функции.

Какой бы код мы ни писали, JS-движок внутренне оборачивает его в основной метод, например:

main(){//main wrapper method created by engine
//Developer's code goes here
}
This

Это называется глобальной областью.

So:

Цепочка областей видимости - это объект, который содержит ссылку на ВО текущей функции, а также на ВО всей ее родительской функции.

Чтобы лучше понять это, давайте настроим приведенный выше пример:

var scopingExample = "Scoping sample string";// Variable declared in //global scope
function testScopingConcept(){
 var innerScopedVariable = "Inside the test function";// Variable //declared in inner scope of testScopingConcept function
 console.log(scopingExample);//prints: This is a new string
 console.log(innerScopedVariable);//prints: This is a new string
}
testScopingConcept();

Если вы выполните указанную выше функцию, вы получите:

Scoping sample string
Inside the test function

testScopingConcept function может печатать scopingExample variable, потому что он также имеет доступ к области родительской функции. Этому способствует Scoping Chain.

c) this: будучи разработчиком JS, вы должны были использовать переменную this в своем коде. Инициализация this happens во время создания объекта контекста времени.

2) Стек выполнения:

Стек выполнения можно объяснить как стек объектов контекста выполнения - когда функция выполняется, ее объект контекста выполнения создается и помещается на вершину стека. По завершении данной функции контекст ее выполнения удаляется из стека.

Поскольку это стек, используется шаблон «первым пришел - последний вышел», и самый новый созданный контекст выполнения будет первым, который будет удален из стека. По той же схеме, пока стек не опустеет.

На приведенном выше изображении очень четко проиллюстрирован Execution-Stack в действии:

  • Контекст выполнения текущей функции помещается вверху.
  • Глобальный контекст находится внизу, так как это первый созданный EC.
  • N + 1 изображает вызов функции, которая вызывается из глобальной области видимости, и, следовательно, его EC помещается поверх глобального EC.
  • Точно так же N + 2 помещается поверх N + 1, а текущий EC - поверх N + 2.
  • Зеленая стрелка показывает движение вызовов функций вверх - когда вызывающая функция (N + 1) передает выполнение вызываемой функции (N + 2).
  • Красная стрелка обозначает движение вниз, т.е. когда выполнение «вызываемой» функции (N + 2) завершено и выполнение возвращается к «вызываемой» функции (N + 1). EC вызываемой (N + 2) функции удаляется из ES.
  • Точно так же, когда выполнение функций N + 2 и N + 1 завершено, их соответствующие EC удаляются из стека.

3) API-интерфейс браузера и веб-интерфейс и среда выполнения узла:

Вы, должно быть, довольно часто встречали этот причудливый термин «время выполнения», но что это, черт возьми ????

Обычно, как веб-разработчики, мы видим JS только в сочетании с браузерами, но, напротив, язык программирования JS в значительной степени независим и зависит только от механизма выполнения JS, такого как Chrome V8 или Mozilla SpiderMonkey.

Браузеру нужен JS для выполнения вычислений во время выполнения или для обработки событий, поскольку браузеры используют язык программирования JS. Для этого браузеры используют механизмы выполнения JS, такие как V8, для выполнения JS. Мы, как разработчики, пишем наш код на JS и передаем его браузеру, который затем использует V8 для анализа нашего кода и его выполнения.

Стандартный язык JS не имеет специальной веб-обработки, такой как прослушивание событий или чтение / запись в DOM или понимание объекта окна, поскольку эти браузеры создают свои пользовательские оболочки вокруг движков JS, чтобы можно было поддерживать операции, специфичные для Интернета.

Вот почему браузеры называются runtime в контексте JS - поскольку они содержат механизмы JS, а также обертывают их настраиваемыми функциями для поддержки конкретных требований Интернета.

Если вы посмотрите на изображение выше:

  • «Механизм выполнения JS» - это фактический механизм JS (V8 для chrome), который отвечает за обработку стандартного кода JS. Сюда входят стандартные функции, предоставляемые языком программирования JS, такие как переменные, функции, область видимости, цепочка областей видимости, контекст выполнения, область выполнения и все другие функции, необходимые для независимой работы языка программирования.
  • «Веб-API» - это оболочка, предоставляемая реализациями браузера. WebApi не являются частью стандартного языка программирования JS.
  • Веб-API (-ы) предоставляют веб-обработчики, такие как AJAX, события (например, onKeyPress или onBlur и другие), зная объект окна или запись / чтение в DOM.
  • Поддержка асинхронного поведения (setTimeOut или setInterval) также является частью webApi.
  • Node также является средой выполнения, которая предоставляет аналогичную оболочку для JS для работы на стороне сервера, так же, как браузеры делают это на стороне клиента.

Интересный факт: даже консоль является частью WebApi, т.е. console.log не поддерживается стандартным языком программирования JS.

4) Обратный вызов или очередь задач:

Для этого нам сначала нужно понять асинхронное поведение, пожалуйста, прочтите и поймите концепции, обсуждаемые в https://medium.com/@pravngaur/unthreading-asynchronous-js-39fdf57486ec

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

Как вы теперь знаете, нетривиальные задачи можно отложить с помощью асинхронных обратных вызовов. После регистрации этого асинхронного обратного вызова движок JS возвращается в стек выполнения и продолжает обрабатывать оставшиеся синхронные задачи.

Итак, на изображении ниже методы showText () и main () - это синхронные задачи в ES, которые необходимо возобновить после регистрации асинхронного обратного вызова usingsetTimeOut method.

Зарегистрированный (с помощью метода setTimeOut) обратный вызов отправляется в очередь задачи / обратного вызова.

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

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

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

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

Как только все синхронные задачи выполнены, он начинает выбирать ожидающие асинхронные задачи из очереди задач и помещать их в стек выполнения для обработки.

Я надеюсь, что это поможет вам лучше понять эти ключевые концепции. Как только вы это прочтете, это станет основой для дальнейших исследований. На Youtube есть потрясающие видео с конференций JS по всем этим темам, я очень рекомендую эти видео.

Спасибо за вашу поддержку, которая мотивирует меня делиться своим опытом !!