Прочитайте «Вы не знаете JavaScript · Том 1» 1-1 Какова область применения?

JavaScript

Мо Яньмэй предложит вам прочитать «Чего вы не знаете».JavaScript》 мир серии, углубленныйJavaScriptВнутри языка выяснитьJavaScriptНазначение каждого компонента — узнать, зачем он нужен.

каков охват

  • Вопрос 1: Где хранятся переменные?
  • Вопрос 2: Как программы находят их, когда они им нужны?

1.1 Принцип составления

Обычно ставятJavaScriptклассифицируется как "динамичный" или "объяснить исполнениеязыке, но на самом деле этоскомпилированный язык, не компилируется раньше времени, а скомпилированные результаты не переносятся в распределенные системы.

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

В традиционных компилируемых языках три шага перед выполнением вместе называются "компилировать".

  • сегментация слов/лексический анализ (Tokenizing/Lexing)

    Разбивает строку символов на осмысленные (для языка программирования) фрагменты кода, называемые лексическими единицами (token).

    var a = 2;
    

    разбивается на лексические единицы:var,a,=,2,;. Если пробелы значимы в языке, они рассматриваются как лексические единицы, в противном случае — нет.

  • разбор/разбор(Parsing)

    Преобразует поток лексических единиц (массивов) в "абстрактное синтаксическое дерево"(Abstract Syntax Tree , AST).

    var a = 2;
    

    Абстрактное синтаксическое дерево приведенного выше кода выглядит так:

    • VariableDeclarationверхний узел
      • Identiferдочерний узел, значение равноa
      • AssignmentExpressionдочерний узел
        • NumericLiteralдочерний узел, значение равно2
  • генерация кода

    БудуASTПроцесс преобразования в исполняемый код называется генерацией кода. Этот процесс зависит от языка, целевой платформы и т. д.

    То есть каким-то образомvar a = 2 ;изASTПреобразован в набор машинных инструкций для создания переменнойa, и сохраните значение вaсередина.

    Движок может создавать и хранить переменные по мере необходимости.

1.2 Понимание масштаба

1.2.1 Список актеров

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

1.2.2 Диалог

JavaScriptкак работает двигательJavaScriptкод?

Напримерvar a = 2;Есть 2 разных объявления, и присваивание переменной выполняет два действия.

  • встретитьvar a, На этапе компиляции компилятор сначала запрашивает текущую область видимости, есть ли переменная в наборе областей видимости.a, если она не существует, объявить новую переменную с именемa; затем компилятор сгенерирует код, необходимый для работы движка во время выполнения, обрабатываяa = 2эта операция присваивания.
  • встретить (a = 2), на этапе выполнения среда выполнения движка сначала запрашивает область, чтобы найти переменную в областиa, если найдено, установить значение2назначить переменнойa, в противном случае движок поднимает руку и выдает исключение.

1.2.3 Компилятору есть что сказать

  • Как понять взаимосвязь между движком, компилятором и областью видимости

    • Код сначала компилируется, а затем выполняется.Когда компилятор генерирует код на втором этапе процесса компиляции, когда движок выполняет его, он ищет переменную поaчтобы определить, было ли оно объявлено.
    • Процессу поиска помогает область действия, но то, как механизм выполняет поиск, повлияет на окончательный результат поиска. правильноJavaScriptТребования к производительности двигателя очень высоки.
  • Есть два способа поиска двигателя:RHSа такжеLHS

    • LHSЗапрос (левая сторона): Найдите контейнер самой переменной и присвойте ему значение, то есть, кто является целью операции присваивания. Напримерa = 2;,для= 2Эта операция присваивания находит цель.
    • RHSЗапрос (не левая сторона): найти значение переменной, понимаемой какretrieve his source value, то есть кто является источником операции присваивания. Например:console.log( a );, вам нужно получить переменнуюaзначение, переменнаяaизRHSзапросить и передать значениеconsole.log(...).
function foo(a){
	console.log( a ); //2
}
foo(2);

Вышеприведенный код имеет 1 местоLHSСпрос, 3 местаRHSЗапрос.

  • LHSЗапросы:
    • скрытыйa = 2в, в2передается в качестве параметраfoo(...)функция, параметрaпровестиLHSЗапрос
  • RHSЗапросы:
    • последняя строкаfoo(...)Для вызова функции требуетсяfooпровестиRHSзапрос, означающий "найтиfooоценить и дать мне", а также(...)иметь в видуfooЗначение функции должно быть выполнено, поэтому лучше действительно указывать значение типа функции.
    • console.log( a );средняя параaпровестиRHSЗапросить и передать полученное значение вconsole.log(...).
    • console.log(...)сам по себе правconsoleвозражать против выполненияRHSзапрос, и проверьте, не вызывается ли одно из полученных значенийlogМетоды.

1.3 Вложение области видимости

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

  • Если целью поиска является назначение переменной, используйтеLHSЗапрос; если целью является получение значения переменной, используетсяRHSЗапрос.
  • Оператор присваивания приведет кLHSЗапрос.=Оператор или операция с аргументом, переданным при вызове функции, приводит к присваиванию в связанной области.

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

1.4 Исключения

Зачем различатьLHSа такжеRHS? Два запроса ведут себя по-разному, если переменная не была объявлена ​​(переменная не может быть найдена ни в одной области).

function foo(a){
	console.log(a + b);
	b = a;
}
foo(2);

к "не объявлен" ПеременныеbпровестиRHSПри запросе его нельзя найти ни в одной из соответствующих областей.

ReferenceErrorсвязано с ошибкой различения масштаба, в то время какTypeErrorЭто означает, что идентификация области прошла успешно, но операция над результатом недопустима или необоснованна.

  • RHSЗапрос не может найти нужную переменную в цепочке областей видимости, движок выдаетReferenceErrorаномальный.
  • В нестрогом режимеLHSЗапрос не ищет нужную переменную в цепочке областей видимости, переменная с таким именем создается в глобальной области видимости и возвращается в движок.
  • В строгом режиме (ES5запускать, запрещать автоматическое или неявное создание глобальных переменных),LHSЗапрос завершается ошибкой и не создает и не возвращает глобальную переменную, движок выдает то же самоеRHSКогда запрос терпит неудачу что-то вродеReferenceErrorаномальный.
  • существуетRHSКогда запрос будет успешным, движок вызовет необоснованную операцию над переменной.TypeErrorаномальный. (например, вызов функции для значения нефункционального типа или ссылкаnullилиundefinedсвойства в значении типа).

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

использованная литература: Блог Муйи Ян

Историческая статья: 【Перевод】30 секунд ES6 (1)