что такое call stack js

Контекст выполнения и стек вызовов в JavaScript

что такое call stack js. Смотреть фото что такое call stack js. Смотреть картинку что такое call stack js. Картинка про что такое call stack js. Фото что такое call stack js

Если вы — JavaScript-разработчик или хотите им стать, это значит, что вам нужно разбираться во внутренних механизмах выполнения JS-кода. В частности, понимание того, что такое контекст выполнения и стек вызовов, совершенно необходимо для освоения других концепций JavaScript, таких, как поднятие переменных, области видимости, замыкания. Материал посвящён контексту выполнения и стеку вызовов в JavaScript.

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

Контекст выполнения (execution context) — это, если говорить упрощённо, концепция, описывающая окружение, в котором производится выполнение кода на JavaScript. Код всегда выполняется внутри некоего контекста.

Типы контекстов выполнения

В JavaScript существует три типа контекстов выполнения:

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

Стек выполнения (execution stack), который ещё называют стеком вызовов (call stack), это LIFO-стек, который используется для хранения контекстов выполнения, создаваемых в ходе работы кода.

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

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

Изучим эту идею с помощью следующего примера:

что такое call stack js. Смотреть фото что такое call stack js. Смотреть картинку что такое call stack js. Картинка про что такое call stack js. Фото что такое call stack js

Вот как будет меняться стек вызовов при выполнении этого кода.

что такое call stack js. Смотреть фото что такое call stack js. Смотреть картинку что такое call stack js. Картинка про что такое call stack js. Фото что такое call stack js

Когда вышеприведённый код загружается в браузер, JavaScript-движок создаёт глобальный контекст выполнения и помещает его в текущий стек вызовов. При выполнении вызова функции first() движок создаёт для этой функции новый контекст и помещает его в верхнюю часть стека.

Когда функция first() завершает работу, её контекст извлекается из стека и управление передаётся глобальному контексту. После того, как весь код оказывается выполненным, движок извлекает глобальный контекст выполнения из текущего стека.

О создании контекстов и о выполнении кода

До сих пор мы говорили о том, как JS-движок управляет контекстами выполнения. Теперь поговорим о том, как контексты выполнения создаются, и о том, что с ними происходит после создания. В частности, речь идёт о стадии создания контекста выполнения и о стадии выполнения кода.

Стадия создания контекста выполнения

Перед выполнением JavaScript-кода создаётся контекст выполнения. В процессе его создания выполняются три действия:

Концептуально контекст выполнения можно представить так:

что такое call stack js. Смотреть фото что такое call stack js. Смотреть картинку что такое call stack js. Картинка про что такое call stack js. Фото что такое call stack js

Привязка this

В глобальном контексте выполнения this содержит ссылку на глобальный объект (как уже было сказано, в браузере это объект window ).

В контексте выполнения функции значение this зависит от того, как именно была вызвана функция. Если она вызвана в виде метода объекта, тогда значение this привязано к этому объекту. В других случаях this привязывается к глобальному объекту или устанавливается в undefined (в строгом режиме). Рассмотрим пример:

что такое call stack js. Смотреть фото что такое call stack js. Смотреть картинку что такое call stack js. Картинка про что такое call stack js. Фото что такое call stack js

Лексическое окружение

Проще говоря, лексическое окружение — это структура, которая хранит сведения о соответствии идентификаторов и переменных. Под «идентификатором» здесь понимается имя переменной или функции, а под «переменной» — ссылка на конкретный объект (в том числе — на функцию) или примитивное значение.

В лексическом окружении имеется два компонента:

Существует два типа лексических окружений:

Существует два типа записей окружения:

В результате, в глобальном окружении запись окружения представлена объектной записью окружения, а в окружении функции — декларативной записью окружения.

Лексическое окружение можно представить в виде следующего псевдокода:

что такое call stack js. Смотреть фото что такое call stack js. Смотреть картинку что такое call stack js. Картинка про что такое call stack js. Фото что такое call stack js

Окружение переменных

Окружение переменных (Variable Environment) — это тоже лексическое окружение, запись окружения которого хранит привязки, созданные посредством команд объявления переменных ( VariableStatement ) в текущем контексте выполнения.

Так как окружение переменных также является лексическим окружением, оно обладает всеми вышеописанными свойствами лексического окружения.

Рассмотрим примеры, иллюстрирующие то, что мы только что обсудили:

что такое call stack js. Смотреть фото что такое call stack js. Смотреть картинку что такое call stack js. Картинка про что такое call stack js. Фото что такое call stack js

Схематичное представление контекста выполнения для этого кода будет выглядеть так:

что такое call stack js. Смотреть фото что такое call stack js. Смотреть картинку что такое call stack js. Картинка про что такое call stack js. Фото что такое call stack js

То что мы только что описали, называется «поднятием переменных» (Hoisting). Объявления переменных «поднимаются» в верхнюю часть их лексической области видимости до выполнения операций присвоения им каких-либо значений.

Стадия выполнения кода

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

Итоги

Только что мы обсудили внутренние механизмы выполнения JavaScript-кода. Хотя для того, чтобы быть очень хорошим JS-разработчиком, знать всё это и не обязательно, если у вас имеется некоторое понимание вышеописанных концепций, это поможет вам лучше и глубже разобраться с другими механизмами языка, с такими, как поднятие переменных, области видимости, замыкания.

Источник

Контекст выполнения и стек вызовов в JavaScript

Если вы — JavaScript-разработчик или хотите им стать, это значит, что вам нужно разбираться во внутренних механизмах выполнения JS-кода. В частности, понимание того, что такое контекст выполнения и стек вызовов, совершенно необходимо для освоения других концепций JavaScript, таких, как поднятие переменных, области видимости, замыкания. Материал, перевод которого мы сегодня публикуем, посвящён контексту выполнения и стеку вызовов в JavaScript.

что такое call stack js. Смотреть фото что такое call stack js. Смотреть картинку что такое call stack js. Картинка про что такое call stack js. Фото что такое call stack js

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

Контекст выполнения (execution context) — это, если говорить упрощённо, концепция, описывающая окружение, в котором производится выполнение кода на JavaScript. Код всегда выполняется внутри некоего контекста.

▍Типы контекстов выполнения

В JavaScript существует три типа контекстов выполнения:

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

Стек выполнения (execution stack), который ещё называют стеком вызовов (call stack), это LIFO-стек, который используется для хранения контекстов выполнения, создаваемых в ходе работы кода.

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

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

Изучим эту идею с помощью следующего примера:

Вот как будет меняться стек вызовов при выполнении этого кода.

что такое call stack js. Смотреть фото что такое call stack js. Смотреть картинку что такое call stack js. Картинка про что такое call stack js. Фото что такое call stack js

Состояние стека вызовов

Когда вышеприведённый код загружается в браузер, JavaScript-движок создаёт глобальный контекст выполнения и помещает его в текущий стек вызовов. При выполнении вызова функции first() движок создаёт для этой функции новый контекст и помещает его в верхнюю часть стека.

Когда функция first() завершает работу, её контекст извлекается из стека и управление передаётся глобальному контексту. После того, как весь код оказывается выполненным, движок извлекает глобальный контекст выполнения из текущего стека.

О создании контекстов и о выполнении кода

До сих пор мы говорили о том, как JS-движок управляет контекстами выполнения. Теперь поговорим о том, как контексты выполнения создаются, и о том, что с ними происходит после создания. В частности, речь идёт о стадии создания контекста выполнения и о стадии выполнения кода.

▍Стадия создания контекста выполнения

Перед выполнением JavaScript-кода создаётся контекст выполнения. В процессе его создания выполняются три действия:

Привязка this

В глобальном контексте выполнения this содержит ссылку на глобальный объект (как уже было сказано, в браузере это объект window ).

В контексте выполнения функции значение this зависит от того, как именно была вызвана функция. Если она вызвана в виде метода объекта, тогда значение this привязано к этому объекту. В других случаях this привязывается к глобальному объекту или устанавливается в undefined (в строгом режиме). Рассмотрим пример:

Лексическое окружение

Проще говоря, лексическое окружение — это структура, которая хранит сведения о соответствии идентификаторов и переменных. Под «идентификатором» здесь понимается имя переменной или функции, а под «переменной» — ссылка на конкретный объект (в том числе — на функцию) или примитивное значение.

В лексическом окружении имеется два компонента:

Лексическое окружение можно представить в виде следующего псевдокода:

Окружение переменных

Окружение переменных (Variable Environment) — это тоже лексическое окружение, запись окружения которого хранит привязки, созданные посредством команд объявления переменных ( VariableStatement ) в текущем контексте выполнения.

Так как окружение переменных также является лексическим окружением, оно обладает всеми вышеописанными свойствами лексического окружения.

Рассмотрим примеры, иллюстрирующие то, что мы только что обсудили:

Схематичное представление контекста выполнения для этого кода будет выглядеть так:

Только что мы только что описали, называется «поднятием переменных» (Hoisting). Объявления переменных «поднимаются» в верхнюю часть их лексической области видимости до выполнения операций присвоения им каких-либо значений.

▍Стадия выполнения кода

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

Итоги

Только что мы обсудили внутренние механизмы выполнения JavaScript-кода. Хотя для того, чтобы быть очень хорошим JS-разработчиком, знать всё это и не обязательно, если у вас имеется некоторое понимание вышеописанных концепций, это поможет вам лучше и глубже разобраться с другими механизмами языка, с такими, как поднятие переменных, области видимости, замыкания.

Уважаемые читатели! Как вы думаете, о чём ещё, помимо контекста выполнения и стека вызовов, полезно знать JavaScript-разработчикам?

Источник

Как работает JS: обзор движка, механизмов времени выполнения, стека вызовов

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

Анализ статистики GitHub показывает, что по показателям активных репозиториев и push-запросов, JavaScript находится на первом месте, да и в других категориях он показывает довольно высокие позиции.

что такое call stack js. Смотреть фото что такое call stack js. Смотреть картинку что такое call stack js. Картинка про что такое call stack js. Фото что такое call stack js
Статистические сведения по JavaScript с GitHub

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

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

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

Обзор

Почти все слышали, в самых общих чертах, о JS-движке V8, и большинству разработчиков известно, что JavaScript — однопоточный язык, или то, что он использует очередь функций обратного вызова.

Здесь мы поговорим, на довольно высоком уровне, о выполнении JS-кода. Зная о том, что, на самом деле, происходит при выполнении JavaScript, вы сможете писать более качественные программы, которые выполняются без «подвисаний» и разумно используют имеющиеся API.

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

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

Движок JavaScript

V8 от Google — это широко известный JS-движок. Он используется, например, в браузере Chrome и в Node.js. Вот как его, очень упрощённо, можно представить:

что такое call stack js. Смотреть фото что такое call stack js. Смотреть картинку что такое call stack js. Картинка про что такое call stack js. Фото что такое call stack js
Упрощённое представление движка V8

На нашей схеме движок представлен состоящим из двух основных компонентов:

Механизмы времени выполнения

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

что такое call stack js. Смотреть фото что такое call stack js. Смотреть картинку что такое call stack js. Картинка про что такое call stack js. Фото что такое call stack js
Движок, цикл событий, очередь функций обратного вызова и API, предоставляемые браузером

Стек вызовов

JavaScript — однопоточный язык программирования. Это означает, что у него один стек вызовов. Таким образом, в некий момент времени он может выполнять лишь какую-то одну задачу.

Стек вызовов — это структура данных, которая, говоря упрощённо, записывает сведения о месте в программе, где мы находимся. Если мы переходим в функцию, мы помещаем запись о ней в верхнюю часть стека. Когда мы из функции возвращаемся, мы вытаскиваем из стека самый верхний элемент и оказываемся там, откуда вызывали эту функцию. Это — всё, что умеет стек.

Рассмотрим пример. Взгляните на следующий код:

Когда движок только начинает выполнять этот код, стек вызовов пуст. После этого происходит следующее:
что такое call stack js. Смотреть фото что такое call stack js. Смотреть картинку что такое call stack js. Картинка про что такое call stack js. Фото что такое call stack js
Стек вызовов в ходе выполнения программы

Каждая запись в стеке вызовов называется стековым кадром.

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

Если выполнить это в Chrome (предполагается, что код находится в файле foo.js ), мы увидим следующие сведения о стеке:

что такое call stack js. Смотреть фото что такое call stack js. Смотреть картинку что такое call stack js. Картинка про что такое call stack js. Фото что такое call stack js
Трассировка стека после возникновения ошибки

Если будет достигнут максимальный размер стека, возникнет так называемое переполнение стека. Произойти такое может довольно просто, например, при необдуманном использовании рекурсии. Взгляните на этот фрагмент кода:

В определённый момент, однако, объём данных о вызовах функции превысит размер стека вызовов и браузер решит вмешаться, выдав ошибку:

что такое call stack js. Смотреть фото что такое call stack js. Смотреть картинку что такое call stack js. Картинка про что такое call stack js. Фото что такое call stack js
Превышение максимального размера стека вызовов

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

Однако, и у исполнения кода в однопоточном режиме тоже есть определённые ограничения. Учитывая то, что у JavaScript имеется один стек вызовов, поговорим о том, что происходит, когда программа «тормозит».

Параллельное выполнение кода и цикл событий

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

«А в чём тут проблема?», — спросите вы. Проблема заключается в том, что до тех пор, пока в стеке вызовов имеется выполняющаяся функция, браузер не может выполнять другие задачи — он оказывается заблокированным. Это означает, что браузер не может выводить ничего на экран, не может выполнять другой код. Он просто останавливается. Подобные эффекты, например, несовместимы с интерактивными интерфейсами.

Однако, это — не единственная проблема. Если браузер начинает заниматься обработкой тяжёлых задач, он может на достаточно долгое время перестать реагировать на какие-либо воздействия. Большинство браузеров в подобной ситуации выдают ошибку, спрашивая пользователя о том, хочет ли он завершить выполнение сценария и закрыть страницу.

что такое call stack js. Смотреть фото что такое call stack js. Смотреть картинку что такое call stack js. Картинка про что такое call stack js. Фото что такое call stack js

Браузер предлагает завершить выполнение страницы

Пользователям подобные вещи точно не понравятся.

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

Итоги

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

Уважаемые читатели! Этот материал — первый в серии «How JavaScript Works» из блога SessionStack. Уже опубликован второй — посвящённый особенностям V8 и техникам оптимизации кода. Как по-вашему, стоит ли его переводить?

Источник

Что такое call stack js

что такое call stack js. Смотреть фото что такое call stack js. Смотреть картинку что такое call stack js. Картинка про что такое call stack js. Фото что такое call stack js

Apr 14, 2018 · 5 min read

Стек вызова функций (Call stack in programming languages)

Как рассматривать стек вызова функции (Call Stack) в контексте языков программирования. Хочу сказать, что стек вызова не совсем то, что демонстрирует нам большинство материалов. Чтобы окончательно понять что такое стек вызова, необходимо вернуться к азам и рассмотреть как работает стек вызова в операционной системе, почему именно так? Потому что нельзя рассматривать стек вызова функций оторванно от физической памяти и возможностью управления ею и тем самым не надо забывать, что стек вызова функций это не «виртуальная» операция, а конкретное место в памяти выделяемое операционной системой для выполнение программного кода функции, которая была запущена внутренним или внешним API (будь-то браузера, IDE или движка какого либо языка).

Хочу определить что такое стека вызова функции в низкоуровневых (low-level programming languages) языках (Assembler, C++):

(В современных низкоуровневых языках есть современные библиотеки позволяющие поддерживать работу ООП и контролировать стек функции не на физическом уровне, а использованием вывода консоли: Poppy, Pantheios)

Шаг 1: запуск лейаута кода.

В лейауте кроме самих инструкций находится дополнительная информация (переменные, декларативные данные, дополнительные технические данные и …)

Получив первую инструкцию о запуске ОС начинает строить стек. Сначала выделяет физическое место на кластерах памяти и заполняет его данными, но какими:

Инструкция получена, создается сам стек в котором основная часть — выделенное место для выполнения операций, а сегмент стека для хранения данных для возврата результата выполнения функции.

что такое call stack js. Смотреть фото что такое call stack js. Смотреть картинку что такое call stack js. Картинка про что такое call stack js. Фото что такое call stack js

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

Инструкция возврата вызова, это не место вызова этой функции, а следующая за ней инструкция.

Сегмент стека (который мы сейчас по простоте называем стеком вызова) это отдельный участок памяти, в котором храняться инструкции о возврате результатов вызванных функции. Используется метод: кто пришел последний — уйдет первый (LIFO).

В языках подобных С++ имплементированы два метода: Call и Ret, Call создает инструкцию с адресом(в бинарной нотации) и кладет на верхний уровень стека, Ret не содержит адреса, этот метод просто забирает верхнюю инструкцию и возвращает нас по указанному адресу. Сам стек, после возвращения данных и выполнения функций уничтожается и данные из него недоступны.

что такое call stack js. Смотреть фото что такое call stack js. Смотреть картинку что такое call stack js. Картинка про что такое call stack js. Фото что такое call stack js

Далее необходимо понять, как высокоуровневые языки реализовывают работу стека вызова. Давайте рассмотрим два случая: языки использующие многопоточность и однопоточные языки. Почему именно такие варианты? Потому что именно многопоточность (multithreading) и однопоточность определяет взаимодействие виртуальной и физической памяти ресурса.

Языки использующие многопоточность рассмотрим на примере Java.

что такое call stack js. Смотреть фото что такое call stack js. Смотреть картинку что такое call stack js. Картинка про что такое call stack js. Фото что такое call stack js

что такое call stack js. Смотреть фото что такое call stack js. Смотреть картинку что такое call stack js. Картинка про что такое call stack js. Фото что такое call stack js

В движок java имплементирована специальная коллекция Stack, у которой есть два метода push(добавит данные) и pop(удалить данные). Виртуальная машина Javaведет запись всех вызванных функций и с каждым вызовом функции создает StackTraceElement. После завершения выполнения функции StackTraceElement уничтожается, поэтому информация о стеке вызовов всегда актуальная. С Помощью метода getMethodName можно всегда получить информацию о методе верхнего элемента StackTraceElement, а значит о методе вызова функции.

что такое call stack js. Смотреть фото что такое call stack js. Смотреть картинку что такое call stack js. Картинка про что такое call stack js. Фото что такое call stack js

Javascript: Javascript однопоточный скриптовый язык использующий очередь функций обратного вызова(callback functions queue) с методом FIFO (первый пришел — первый уйдешь).

Два варианта взаимодействия физической и виртуальной памяти в Javascript:

Сам стек как и базовые использует LIFO, а очередь колбэков — FIFO. Так же в V8 имплементированы методы push и pop, декларация идентична методам, реализованным в Java.

Методы Javascript использующие таймеры использующие API OS и таймеры которые работают на API браузера. Таймеры всегда передвигают выполнение функции-колбэка в конец стека вызовов. Что это значит? Это значит, что в браузере выполняя методы setTimeout, setInterva сначала запускается таймер, а лишь потом функция-колбэк попадает в очередь ожидания. Если в момент попадания колбэка стек переполнен, колбэку приходится ждать своей очереди. Таймеры запущенные вне браузера реализованы на основании либо внутренних методов V8 либо при обращении к API окружения (API OS).

Особенностью языка Javascript является технология ajax или иначе возможность отправки асинхронных запросов (XMLHTTPRequest) и выполнения каких либо операций без задержки выполнения основного кода. XMLHTTPRequest может быть отправлен синхронно, но при этом весь остальной код будет дожидаться либо результата отправки запроса, что порой нецелесообразно. Технология ajax реализована исключительно в браузерах, что делает выделяет Javascript из группы языков использующих async. Асинхронные запросы в JS используют цикл событий с очередью колбэков (event loop with callback queue). В остальных языках программирования тоже есть возможность запуска асинхронного кода (Python (asyncio), C#(async/await)), что позволяет выполнять какие-то операции без задержки выполнения основных функций, принципом тут тоже выступает цикл событий, где функция колбэк помещается в очередь ожидания. Принцип работы очереди — FIFO.

Очень много в сети информации, поэтому кратко.

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

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *