Условие и примечание

  • Основы Javascript
  • Будет объяснена основная внутренняя работа Javascript, но обратите внимание, что объяснение относится только к Javascript, другие языки программирования могут выполнять ту же задачу по-другому.
  • Еще раз подчеркнем, что вам не нужно предварительно знакомиться с внутренней работой Javascript.

Javascript странный

Возможно, вы слышали, что Javascript — один из самых ненавистных, но популярных языков программирования. Есть несколько причин, вызывающих ненависть к Javascript, и они могут различаться у разных людей. Причина, по которой я называю это странным, заключается в том, насколько таинственно это работает. Вот несколько примеров.

Что можно сделать?

Решение проблемы странной работы Javascript заключается в том, чтобы понять, как работает Javascript внутри! В этом уроке мы возьмем одну проблему и поймем, почему это происходит. Давайте начнем!

Проблема..

Я создал простое приложение с файлом index.html и файлом app.js, которое выводит на экран простой Hello, World.

Рассмотрите приведенный ниже пример кода и попытайтесь заметить разницу.

Заметили разницу?

В первом примере кода инициализируется функция hello и favNum, затем вызывается функция и favNum регистрируется напрямую.

Во втором примере кода функции hello и favNum вызываются до их инициализации, что должно дать ошибка, да? Давай проверим!

Пример кода 1 дает ожидаемый результат, а пример кода 2 — нет. Ммм… Функция Hello from hello регистрируется, и favNum дает неопределенное значение? Что это!? Теперь начинается самое интересное, идем дальше!

Подъем

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

Что это значит простыми словами? Взяв пример нашего кода, все переменные и функции, созданные в нашей программе, перемещаются в начало файла, и компилятор понимает код, как наш пример кода 1. Взгляните на код ниже.

Но… Функции дают желаемый результат, почему мы выводим undefined для favNum?

Не определено и не определено (ошибка ссылки)

Очень важно знать разницу между undefined и Reference Error.

undefined в основном означает, что переменная была объявлена, но ей не было присвоено значение нигде в программе, тогда как Ошибка ссылки означает, что переменная даже не была объявлена ​​нигде в программе. программа, поэтому программа не может найти ссылку на эту переменную

Выполнение кода Javascript

Чтобы понять, почему мы становились неопределенными, нам нужно понять, как Javascript работает под капотом — как Javascript присваивает значение своим переменным, идет ли он построчно и выполняет все строки или переходит к определенному методу и выполняет его первым? Чтобы ответить на все эти вопросы, давайте разберемся, что такое контекст выполнения!

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

В JavaScript контекст выполнения — это абстрактное понятие, которое содержит информацию о среде, в которой выполняется текущий код.

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

Назначение переменных

Мы знаем, что выполнение всего кода в Javascript происходит в контексте выполнения. Поэтому назначение переменных происходит в контексте выполнения.

Контекст выполнения состоит из двух компонентов: один компонент называется Переменная среда или просто Компонент памяти, а второй — Поток выполненияилипростоКомпонент кода.

Как вы можете догадаться по самому названию, Variable Environment хранит все переменные в памяти в паре ключ-значение, тогда как Thread of Execution проходит через программу строка за строкой и создает стек, который можно назвать стеком вызовов! Ниже приведена диаграмма, представляющая то же самое.

Теперь давайте разберемся, что произойдет, имея в виду наш пример кода 1. Сначала мы получим ответ пример кода 2.

Итак, что делает Javascript, так это идет построчно, сохраняет каждую часть строки в Thread of Execution. Возьмем, к примеру, приведенный ниже фрагмент кода:

console.log("Waddup");

Внутренняя работа (пример кода 1)

Ниже приведен пример кода 1, на который мы будем ссылаться:

var favNum = 10;
function hello() {
   console.log("Hello");
}
hello();
console.log(favNum);

Итак, что происходит, компилятор проходит построчно, сохраняет код в Thread of Execution и всякий раз, когда видит назначение переменной или объявление функции, сохраняет его в Variable Environment в паре ключ-значение.

Самая забавная часть того, как он сохраняет переменную в Variable Environment, заключается в том, что он не сохраняет напрямую значение переменной favNum как 10.Проходя программу построчно, сохраняет favNum как undefined в среде переменных и при запуске потока выполнения (помните, когда переменной присваивается значение undefined, она также сохраняет код в стеке вызовов/потоке выполнения) сохраняет favNum как 10. Ниже показано, как пара ключ-значение переменной хранится в среде переменных.

key : value
favNum: undefined
// runs the Call Stack or Thread of Execution or Thread Stack
favNum: 10

Назначение функции

Мы поняли, как переменной присваивается значение. Но как функция получает свое значение, становится ли она сначала неопределенной как значение, а затем происходит код внутри нее? Нет! Javascript работает иначе!

Функции в Javascript можно рассматривать как мини-программу в самой программе. Что я имею в виду? Давайте разберемся с этим с помощью нашей диаграммы контекста выполнения.

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

Пошаговое руководство по коду примера 1

Теперь, когда мы знаем, как назначаются переменные и функции. Мы можем понять пример кода 1.

Шаг 1: Заполнение потока выполнения и присвоение неопределенного значения переменным

Шаг 2: Очистка переменной стека

Шаг 3: Очистка функции стека

Когда поток выполнения чист, т. е. пуст, это означает, что вся программа завершена.

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

Доказательство назначения переменных и функций (бонус)

Перейдите в свой любимый редактор кода и создайте базовую веб-программу, подобную той, которую я создал (только с HTML, CSS). Запустите веб-сайт в Chrome и откройте Chrome Dev Tools (Inspect Element).

On Windows: CTR+SHIFT+I

Перейдите на вкладку «Источники» и нажмите на файл сценария, который вы создали. Для меня это app.js. Добавьте отладчик в первую строку. Проверьте изображение ниже и убедитесь, что вы со мной.

Следующее, что нужно сделать, это перезагрузить страницу, чтобы запустился отладчик и мы увидели результаты!

CTR+R

Вы должны увидеть такие результаты. Откройте Scope с правой стороны и разверните Global. Там попробуйте найти переменную favNum.

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

Давайте сделаем то же самое для функции hello. Щелкните следующий значок в отладчике, чтобы перейти к следующей строке. Ниже приведено изображение, показывающее, как функция hello сохраняется в памяти.

Это подтверждает то, как мы думали, как функции хранятся в памяти.

Давайте перейдем к следующей строке, где мы видим, что переменные получают установленные нами значения. (Я поставил 2 точки останова, одну на функцию hello, а другую на переменную favNum, поэтому они у меня в другом разделе. Если вы этого не сделали, найдите переменные в памяти, как вы делали ранее).

Двигаясь к концу программы, вы должны увидеть, что отладчик автоматически закрывается, а стек вызовов полностью пуст.

Вот так! Вы завершили базовое понимание подъема, внутренней работы Javascript, что является наиболее важным при понимании таких тем, но еще многое предстоит понять. Например, пусть vs const. Если вы хорошо поняли и хотите узнать больше, дайте мне знать об этом в разделе комментариев, я сделаю это!

Спасибо за чтение!