Ничего странного здесь нет. V8 компилирует JavaScript непосредственно в машинный код. В результате недоступный код, такой как функция b, удаляется, когда на него никогда не ссылаются. Это общее свойство почти каждого компилятора.
Что мне не хватает ?? Мои концепции неверны ?? Это из-за консоли Chrome ?? Можете ли вы объяснить это поведение ??
В этом фрагменте кода, который отличается от указанного в примере case-1 c, а именно в том, что был удален вызов b
, b
функция была удалена компилятором. В результате вы не видите никаких ссылок на него в отладчике.
case-2
При рассмотрении case-2 вы игнорируете тот факт, что отладчик остановлен не в том месте, чтобы проанализировать внутреннюю область действия function a
. В результате вы видите a
в окне отладки, и это все.
Ваша секция понимания
JS интерпретатор при достижении строки 9 какие команды для выполнения функции a (); создаст новый контекст выполнения для функции a (или мы можем сказать, выделить память в куче для контекста выполнения, который является объектом, и указать на него, верно ??)
Не совсем.
- строка 9: выполнить функцию a () [правильно]
- создать контекст выполнения для функции a [правильно]
- выделить память в куче [неправильно]
- контекст выполнения - это объект [правильно]
- указывает на это [неправильно]
Контекст выполнения - это объект, однако скомпилированная функция - это состояние c Фрейм функции хранится в стеке. Привязка this
- это отдельное значение, которое не ссылается на контекст выполнения, а вместо этого обеспечивает вход для области видимости переменной.
Теперь я знаю, что интерпретатор сначала go будет проходить через все тело функции и выделит место для объявлений переменных и функций в контексте выполнения, созданном в куче.
Это неверно. Как уже отмечалось, интерпретатор работает над скомпилированным кодом. Этот код уже имеет установленный объем памяти. В куче создается указатель, который указывает на скомпилированный код в стеке.
Это видно из правой части изображения, где в локальной области видимости у нас есть ссылочная переменная b к лямбда-выражению функция.
b
не является лямбда-функцией, это было бы var b = () => console.log('Hello i am B');
, и не было бы поднято. Помимо этого, a
- это просто вложенный контекст. b
также скомпилирован, и его ссылка c stati является просто компонентом уже скомпилированного a
. Область видимости и хранение в памяти - это две совершенно разные концепции.
И теперь, после прохождения всего тела функции, интерпретатор выполнит код. Теперь, поскольку у нас уже есть функция b, хранящаяся в контексте выполнения a (или контекст выполнения a знает о b), она выполнит ее. (Вот что такое подъем, верно ??)
Этот код является прямым, поэтому интерпретатор создает указатель на кучу и немедленно выполняет скомпилированный код в стеке. a
выполняется, затем внутри a
, b
выполняется, как отмечено выше.
Подъем - это просто перемещение объявлений в верхнюю часть областей для объявлений function
и var
, но не const
или let
. Подъем просто делает ваш первый пример эквивалентным этому:
function a(){
function b(){
console.log('Hello i am B')
}
console.log('Heloo')
b()
}
a()