предисловие
На Nuggets много дискуссий о масштабе и цепочке контекстов, но мало кто объясняет соответствующие механизмы в JS.Здесь я возьму некоторые знания, оставленные большими парнями, и расскажу о подготовке перед пониманием масштаба. Прочитайте статью с этими вопросами:
-
JavaScript
Как он компилируется и выполняется? - Как запрашивать слой за слоем при поиске области?
-
JavaScript
Какова природа цепочки областей видимости?
Если вы хотите увидеть анализ напрямую, перейдите к:2. Как выполняется JavaScript?
Существуют также сокращенные формулы:Формула цепочки областей видимости
1. Популярность важнее понимания: принцип компиляции
1.1 Сегментация слов/лексический анализ
Эти блоки кода называются токенами, и эти токены составляют массив потоков токенов.
var sum = 30;
// 词法分析后的结果
[
"var" : "keyword",
"sum" : "identifier",
"=" : "assignment",
"30" : "integer",
";" : "eos" (end of statement)
]
1.2 Синтаксический анализ
Преобразует массив потоков токенов в дерево элементов, представляющих синтаксическую структуру программы, которое называется «абстрактным синтаксическим деревом» (Abstract Syntax Tree
, короткоAST
).
1.3 Генерация кода
Абстрактное синтаксическое дерево (AST
) преобразуется в набор машинных инструкций, то есть исполняемый код, который, короче говоря, используется для создания переменной а и сохранения значения 3 в а.
1.4 Различия в процессе компиляции JavaScript
-
JavaScript
В большинстве случаев компиляция происходит за несколько микросекунд (или даже меньше!) до выполнения кода. -
JavaScript
Двигатель исчерпал все средства (например,JIT
, вы можете отложить компиляцию или даже выполнить перекомпиляцию), чтобы обеспечить наилучшую производительность.
2. Как выполняется JavaScript?
-
Основная мысль: все объявления, включая переменные и функции, обрабатываются перед выполнением любого кода.
-
В момент запуска функции создается рабочий носитель AO (Active Object).
2.1 Пример 1
function a(age) {
console.log(age);
var age = 20
console.log(age);
function age() {
}
console.log(age);
}
a(18);
2.1.1 Фаза анализа
В момент запуска функции создайтеAO
(Active Object 活动对象
)
АО (активный объект) эквивалентен несущей
AO = {}
Первым шагом является анализ параметров функции:
形式参数:AO.age = undefined
实参:AO.age = 18
Второй шаг — проанализировать объявление переменной:
// 第3行代码有var age
// 但此前第一步中已有AO.age = 18, 有同名属性,不做任何事
即AO.age = 18
Третий шаг — анализ объявления функции:
// 第5行代码有函数age
// 则将function age(){}付给AO.age
AO.age = function age() {}
Особенности объявления функции: если в AO есть атрибут с тем же именем, что и имя функции, эта функция будет перезаписывать его.
Поскольку функция находится в поле JS, она также является типом переменной.
Конечным результатом этапа анализа является:
AO.age = function age() {}
2.1.2 Фаза выполнения
2.2 Пример 2
function a(age) {
console.log(age);
var age = function () {
console.log('25');
}
}
a(18);
2.2.1 Этап анализа
Первым шагом является анализ параметров функции:
形式参数:AO.age = undefined
实参:AO.age = 18
Второй шаг — проанализировать объявление переменной:
// 第3行代码有函数表达式 var age = function () { console.log('25');}
// 但此前第一步中已有AO.age = 18, 有同名属性,不做任何事
即AO.age = 18
Третий шаг — анализ объявления функции (нет)
Конечным результатом этапа анализа является:
AO.age = 18
2.2.2 Фаза выполнения
2.3 Пример 3
function a(age) {
console.log(age);
var age = function () {
console.log(age);
}
age();
}
a(18);
2.3.1 Фаза анализа
Первым шагом является анализ параметров функции:AO.age = 18
Второй шаг — проанализировать объявление переменной: есть атрибут с таким именем, ничего не делатьAO.age = 18
Третий шаг — анализ объявления функции (нет)
Конечным результатом этапа анализа является:
AO.age = 18
2.3.2 Фаза выполнения
В этот момент многие люди будут сбиты с толку:age();
не должен выводить18
?
код выполняется дляage();
Фактически, он будет проанализирован и выполнен снова.
2.3.3 age()
Анализ и выполнение
// 分析阶段
创建AO对象,AO = {}
第一步,分析函数参数(无)
第二步,分析变量声明(无)
第三步,分析函数声明(无)
分析阶段最终结果是:AO = {}
- когда
age()
мой собственныйAO对象
,Прямо сейчасage.AO
Когда это пустой объект, он будет вызван. - Верхний уровень
AO对象
даa
,Прямо сейчасa.AO
,a.AO
Следующий получается после выполненияa.AO.age = function(){console.log(age);}
- выход
ƒ () { console.log(age); }
`
2.4 Резюме: что такое цепочка областей видимости
Когда каждая функция в JavaScript выполняется, она сначала создает свою собственнуюAO
Найдите соответствующее значение атрибута. Если вы не можете его найти, ищите АО родительской функции, и если вы не можете найти его снова, переходите на следующий уровень.AO
, пока не будет найден большой босс:window
(глобальный охват).
И эта статья образовалась "AO
цепь" естьJavaScript
в цепочке областей.
3.LHS
а такжеRHS
Запрос: два великих оружия цепочки прицелов
Термины LHS и RHS появляются, когда механизм запрашивает переменные. В «Javascript, которого вы не знаете (часть 1)» также есть очень четкое описание. Здесь я хотел бы процитироватьfreecodecamp
Ответ выше, чтобы объяснить:
LHS = присвоение переменной или запись в память. Думайте об этом как о сохранении текстового файла на жесткий диск. RHS = поиск переменных или чтение из памяти. Думайте об этом как об открытии текстового файла с вашего жесткого диска.Learning Javascript, LHS RHS
3.1 Характеристики обоих
- будет запрашиваться во всех областях
- В строгом режиме, когда нужная переменная не найдена, движок выдает
ReferenceError
аномальный. - В нестрогом режиме
LHR
Немного особенного: автоматически создается глобальная переменная - При успешном выполнении запроса, если над значением переменной выполняется необоснованная операция, например, выполняется вызов функции для значения нефункционального типа, движок выдает ошибку
TypeError
аномальный
3.2 Возьмите пример из книги в качестве примера
function foo(a) {
var b = a;
return a + b;
}
var c = foo( 2 );
Посмотрите непосредственно на поиск выполнения:
LHS (запись в память):
c=, a=2(隐式变量分配), b=
RHS (чтение памяти):
读foo(2), = a, a ,b
(return a + b 时需要查找a和b)
Лучше понимать по записи/чтению по памяти, чем по книге?
3.3 ОLHS
а такжеRHS
бросать неправильно
Возьмем два простейших примера:
3.3.1 Неразумная эксплуатация
LHS
На этапе запроса исходный запрос был успешным, ноa
Вызов функции действияa();
, поэтому движок выдаст исключение TypeError.
3.3.2 LHS
бросать неправильно
LHS
Более редкая ситуация: много раз мы не включаем строгий режим, то есть:“use strict”
.
вы можете открыть сейчасchrome
Инструменты отладки, попробуйте следующий вывод кода в строгом/нестрогом режиме соответственно:
“use strict”
function init(a){
b=a+3;
}
init(2);
console.log(b);
3.3.3 RHS
бросать неправильно
4. Формула цепочки содержания
Здесь мы объясняем с картинкой в «Javascript, которого вы не знаете (часть 1)»:
Я также заключилФормула цепочки областей видимости, научим быстро находить вывод:
-
На этапе анализа создается АО.После считывания параметров находятся переменные.Переменные не являются вершиной функции.После завершения вершины будет определена вселенная.
-
В фазе выполнения посмотрите на LR.Если вы не можете найти внешний слой во внутреннем слое, вы не можете найти его, покопавшись в этажах.
Понимание:
За последние несколько дней я искал много информации и обнаружил, что многие из них расплывчаты. Или очень сложный и эзотерический. Или это грубое резюме без систематического введения. Это также является причиной того, что существует так много прицелов и цепочек прицелов, но ни одна из них до конца не изучена (скорее всего из-за овощей)
Сборник авторских статей
- «Узнайте из исходного кода» ответы на вопросы Vue, которые интервьюеры не знают
- JS-операция «Узнать из исходного кода» в исходном коде Vue
- «Учитесь на основе исходного кода» полностью разбирайтесь в параметрах Vue.
- Правильная позиция для обновления vue-cli3 в проекте "Vue Practice"
- Почему вы до сих пор не можете понять цепочку областей видимости JavaScript?