Similar presentations:
Исполняемый код и контекст исполнения в JS
1.
Исполняемый код и контекстисполнения в JS
Дмитрий Нефедов
Старший программист группы систем электронной коммерции
Спортмастер Россия
mailto: [email protected]
2.
В JS нет магии :)var a = 5;
function foo() {
console.log(a);
}
function bar() {
foo();
console.log(a);
var a = 6;
}
bar();
3.
Область видимостиСтатическая область видимости:
Динамическая область видимости:
var x = 10;
x = 10;
function foo() {
console.log(x);
}
procedure foo()
print(x)
end
foo(); // 10
function bar() {
var x = 20;
console.log(x); // 20
foo(); // 10
}
bar();
foo() // 10
procedure bar()
x = 20
foo() // 20
end
bar()
4.
Лексическая область видимостиСпецификация, используемая для определения связи идентификаторов с конкретными
значениями и функциями;
Связано с синтаксической структурой кода, такой как FunctionDeclaration, BlockStatement,
Catch и TryStatement;
Состоит из записи окружения и ссылки на внешнее лексическое окружение;
5.
Пример:var x = 10;
function foo() {
var y = 20;
}
globalEnvironment = {
environmentRecord: {
Object: function,
// etc ...
x: 10
},
outer: null
};
fooEnvironment = {
environmentRecord: {
y: 20
},
outer: globalEnvironment
};
6.
Пример:function foo() {
var x = 10;
function bar() {
var y = 20;
console.log(x + y); // 30
}
function baz() {
var z = 30;
console.log(x + y); // 40
}
}
fooEnvironment = {
environmentRecord: {x: 10},
outer: globalEnvironment
};
barEnvironment = {
environmentRecord: {y: 20},
outer: fooEnvironment
};
bazEnvironment = {
environmentRecord: {z: 30},
outer: fooEnvironment
};
7.
Типы записей окруженияДекларативные записи
Каждая декларативная запись среды связана с областью программы ECMAScript,
содержащей объявления переменных, констант, let, class, module, import и / или функций.
Декларативная запись среды связывает набор идентификаторов, определенных объявлениями,
содержащимися в его области.)
Объектные записи
Запись объектной среды используется для определения связи переменных и функций,
появившихся в глобальном контексте и внутри with-операторов.
8.
Вид декларативной записи окруженияfunction foo(a) {
var b = 10;
function c() {}
}
environment = {
// storage
environmentRecord: {
type: "declarative",
a: <...>,
b: <...>,
c: <...>
},
// reference to the parent environment
outer: <...>
};
9.
Пример объектной записи окруженияvar a = 10;
var b = 20;
with ({a: 30}) {
console.log(a + b); // 50
}
console.log(a + b); // 30, restored
context.lexicalEnv = {
environmentRecord: {a: 10, b: 20},
outer: null
};
previousEnv = context.lexicalEnv;
withEnv = {
environmentRecord: {a: 30},
outer: context.lexicalEnv
};
context.lexicalEnv = withEnv;
context.lexicalEnv = previousEnv;
10.
Контекст исполненияThis
Переменные компоненты среды
Лексические компоненты среды
ExecutionContext = {
ThisBinding: <this value>,
VariableEnvironment: { ... },
LexicalEnvironment: { ... },
}
11.
ThisВ глобальном контексте this - глобальный объект
Внутри контекста функции this определяется формой вызова функции
var foo = {
bar: function () {
console.log(this);
};
};
foo.bar();// "this" === "foo"
var bar = foo.bar;
bar();// "this" === global
this.bar();// "this" === global
bar.prototype.constructor();// "this" === "bar.prototype"
// --- non-Reference cases --(foo.bar = foo.bar)();// "this" === "global" or "undefined"
(foo.bar || foo.bar)();// "this" === "global" or "undefined"
(function () {this;})();//"this" === "global" || "undefined"
12.
Переменные компоненты средыfunction foo(a) {
var b = 20;
}
foo(10);
fooContext.VariableEnvironment = {
environmentRecord: {
arguments: {0: 10, length: 1, callee: foo},
a: 10,
b: 20
},
outer: globalEnvironment
};
13.
Лексические компоненты средыvar a = 10;
foo.[[Scope]] = globalContext.[[VariableEnvironment]];
function foo() {console.log(a);}
// "with"
previousEnvironment =
globalContext.[[LexicalEnvironment]];
with ({a: 20}) {
var bar = function () {
console.log(a);
};
foo(); // 10, from VariableEnv
bar(); // 20, from LexicalEnv
}
foo(); // 10
bar(); // still 20
globalContext.[[LexicalEnvironment]] = {
environmentRecord: {a: 20},
outer: previousEnvironment
};
// "bar" is created
bar.[[Scope]] = globalContext.[[LexicalEnvironment]];
// "with" is completed, restore the environment
globalContext.[[LexicalEnvironment]] =
previousEnvironment;
14.
Инициализация идентификаторовПроцесс определения значения идентификатора, появившегося в контексте, с
использованием лексического компонента в текущем контексте выполнения
function resolveIdentifier(lexicalEnvironment, identifier) {
// если метод вызван из конечного окружения, переменной нет
if (lexicalEnvironment == null) {
throw ReferenceError(identifier + " is not defined");
}
// если значение найдено, возвращаем его Reference
if (lexicalEnvironment.hasBinding(identifier)) {
return new Reference(lexicalEnvironment, identifier);
}
return resolveIdentifier(lexicalEnvironment.outer, identifier);
}
15.
Примерvar a = 10;
(function foo() {
var b = 20;
(function bar() {
var c = 30;
console.log(a + b + c); // 60
})();
})();
resolveIdentifier(bar.[[LexicalEnvironment]], "a") ->
-- bar.[[LexicalEnvironment]] - not found,
-- bar.[[LexicalEnvironment]].outer ->
foo.[[LexicalEnvironment]]) -> not found
-- bar.[[LexicalEnvironment]].outer.outer ->
found reference, value 10