Стандарт ECMA-262 (JavaScript) в картинках, часть 1

в 11:06, , рубрики: ecma-262, ECMAScript, javascript

Стандарт ECMA-262 (JavaScript) в картинках, часть 1 - 1

Про устройство JavaScript написано много статей. В первую очередь, это "JavaScript. Ядро." Дмитрия Сошникова, перевод статьи Ричарда Корнфорда и поста Дмитрия Франка. Но для того чтобы хорошо разобраться в какой-либо технологии лучше обратиться к первоисточникам. В данном случае к стандарту ECMA-262 ECMAScript Language Specification. Я рассматриваю этот пост как облегченный способ начать изучение стандарта. Рекомендую переходить по ссылкам, вчитываться в текст спецификации и составлять собственные схемы.

Как работают замыкания в JavaScript

Основные структуры ECMAScript это execution context, lexical environment и environment record. Они связаны следующим образом:

Стандарт ECMA-262 (JavaScript) в картинках, часть 1 - 2

Кроме VariableEnvironment в execution context есть еще LexicalEnvironment, подробнее про различия можно прочитать в ECMAScript 5 spec: LexicalEnvironment versus VariableEnvironment.
ThisBinding будет рассмотрен в следующей части статьи

В environment record хранятся значения переменных. Если объявить var a = 1, то в текущем record появится {a: 1}. В lexical environment кроме record есть еще поле outer. Outer ссылается на внешний lexical environment, например, в случае вложенных функций.

Поиск переменных начинается с VariableEnvironment текущего контекста. Если переменная с таким именем не найдена в record, то она ищется в outer environment по цепочке.

При запуске программы создаются глобальные context и environment. В качестве record используется global object.

Стандарт ECMA-262 (JavaScript) в картинках, часть 1 - 3

Когда интерпретатор встречает ключевое слово function он создает FunctionObject. В свойство scope созданного FunctionObject записывается ссылка на текущий lexical environment.

Запись function f(){} практически эквивалентна записи var f = function(){} за исключением того, что в первом случае FunctionObject будет создан при входе в блок, содержащий function f(), а во втором при выполнении конкретной строчки.

Стандарт ECMA-262 (JavaScript) в картинках, часть 1 - 4

При каждом вызове функции создаются новые context, environment и record. Контекст кладется в стек, при выходе из функции он уничтожается. В outer созданного environment записывается scope вызываемого FunctionObject. Если функция была объявлена в глобальном контексте, то outer будет указывать на global environment.

Стандарт ECMA-262 (JavaScript) в картинках, часть 1 - 5

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

var x = 1;

function f() {
  var x = 2;
  function g() {
    return x;
  }
  return g;
}

f()();

При вызове функции f создается context и environment для f, а также FunctionObject для function g. В scope записывается ссылка на текущий environment из VariableEnvironment. При выходе из f контекст уничтожается, но environment останется, так как на него есть ссылка из возвращенного FunctionObject.

Стандарт ECMA-262 (JavaScript) в картинках, часть 1 - 6

При вызове возвращенной из f функции g создается контекcт и environment для g. В outer нового environment записывается scope из вызываемого FunctionObject. Поиск переменной x начинается с текущего VariableEnvironment и затем продолжается по outer. В результате будет возвращено значение x = 2.

Стандарт ECMA-262 (JavaScript) в картинках, часть 1 - 7

В следующей части статьи разберем как с точки зрения ECMAScript работает this.

Автор: alvin777

Источник


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js