- PVSM.RU - https://www.pvsm.ru -
Про устройство JavaScript написано много статей. В первую очередь, это "JavaScript. Ядро." Дмитрия Сошникова [1], перевод статьи Ричарда Корнфорда [2] и поста Дмитрия Франка [3]. Но для того чтобы хорошо разобраться в какой-либо технологии лучше обратиться к первоисточникам. В данном случае к стандарту ECMA-262 ECMAScript Language Specification [4]. Я рассматриваю этот пост как облегченный способ начать изучение стандарта. Рекомендую переходить по ссылкам, вчитываться в текст спецификации и составлять собственные схемы.
Основные структуры ECMAScript это execution context [5], lexical environment [6] и environment record [7]. Они связаны следующим образом:
Кроме VariableEnvironment в execution context есть еще LexicalEnvironment, подробнее про различия можно прочитать в ECMAScript 5 spec: LexicalEnvironment versus VariableEnvironment [8].
ThisBinding будет рассмотрен в следующей части статьи
В environment record хранятся значения переменных. Если объявить var a = 1
, то в текущем record появится {a: 1}. В lexical environment кроме record есть еще поле outer. Outer ссылается на внешний lexical environment, например, в случае вложенных функций.
Поиск переменных начинается с VariableEnvironment текущего контекста. Если переменная с таким именем не найдена в record, то она ищется в outer environment по цепочке [9].
При запуске программы создаются глобальные context и environment [10]. В качестве record используется global object.
Когда интерпретатор встречает ключевое слово function он создает FunctionObject [11]. В свойство scope созданного FunctionObject записывается ссылка на текущий lexical environment.
Запись function f(){}
практически эквивалентна записи var f = function(){}
за исключением того, что в первом случае FunctionObject будет создан при входе в блок, содержащий function f()
, а во втором при выполнении конкретной строчки.
При каждом вызове функции создаются новые context, environment и record [12]. Контекст кладется в стек, при выходе из функции он уничтожается. В outer созданного environment записывается scope вызываемого FunctionObject. Если функция была объявлена в глобальном контексте, то outer будет указывать на global environment.
Теперь рассмотрим замыкание, когда одна функция возвращает другую.
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.
При вызове возвращенной из f функции g создается контекcт и environment для g. В outer нового environment записывается scope из вызываемого FunctionObject. Поиск переменной x начинается с текущего VariableEnvironment и затем продолжается по outer. В результате будет возвращено значение x = 2
.
В следующей части статьи [13] разберем как с точки зрения ECMAScript работает this.
Автор: alvin777
Источник [14]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/115186
Ссылки в тексте:
[1] "JavaScript. Ядро." Дмитрия Сошникова: http://dmitrysoshnikov.com/ecmascript/ru-javascript-the-core/
[2] перевод статьи Ричарда Корнфорда: https://habrahabr.ru/post/223459/
[3] поста Дмитрия Франка: https://habrahabr.ru/company/hexlet/blog/266443/
[4] ECMA-262 ECMAScript Language Specification: http://www.ecma-international.org/ecma-262/5.1/
[5] execution context: http://www.ecma-international.org/ecma-262/5.1/#sec-10.3
[6] lexical environment: http://www.ecma-international.org/ecma-262/5.1/#sec-10.2
[7] environment record: http://www.ecma-international.org/ecma-262/5.1/#sec-10.2.1
[8] ECMAScript 5 spec: LexicalEnvironment versus VariableEnvironment: http://www.2ality.com/2011/04/ecmascript-5-spec-lexicalenvironment.html
[9] то она ищется в outer environment по цепочке: http://www.ecma-international.org/ecma-262/5.1/#sec-10.2.2.1
[10] создаются глобальные context и environment: http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.1.1
[11] создает FunctionObject: http://www.ecma-international.org/ecma-262/5.1/#sec-13.2
[12] создаются новые context, environment и record: http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.3
[13] В следующей части статьи: https://habrahabr.ru/post/279733/
[14] Источник: https://habrahabr.ru/post/279421/
Нажмите здесь для печати.