Замыкания
Глобальные переменные и глобальные функции - свойства глобального объекта. В браузере это window.
var a = 5;
window.a; // 5
или так
window.b = 12;
b; // 12
Локальные переменные и локальные функции находятся внутри других функций.
[[Scope]] = window
var a = 5;
window.a; // 5
или так
window.b = 12;
b; // 12
Локальные переменные и локальные функции находятся внутри других функций.
Выполнение js-кода
I стадия: инициализация
- ищет все функции, которые объявлены как function declaration и их код, то есть функции сразу создаются работающими;
- ищет все переменные и функции, объявленные как function expression, но значений им не присваивает, то есть они undefined;
- значения переменным и функциям, которые function expression, присваивается тогда, когда выполнение кода доходит до них.
II стадия - выполнение
Переменные, созданные без объявления
Такая переменная всегда глобальная, даже если создаётся внутри функции. Но в новом стандарте так делать нельзя:
use strict
a = 3; // SyntaxError
И такая переменная не инициализируется, то есть, пока до неё не дойдёт код, скрипт о её существовании не знает.
! Циклы, несмотря на то, что у них тоже есть фигурные скобки, на область видимости не влияют
Работа внутри функции
При запуске функции создаётся скрытый объект Lexical Enviroment - лексическое окружение.
Инициализация (подготовка к выполнению) внутри него выполняется точно так же, как и в глобальном объекте window.
1. Интерпретатор создаёт пустой объект Lexical Enviroment
2. Туда помещаются параметры функции и переменные, объявленные внутри неё
3. Функция выполняется. Параметрам и переменным присваиваются значения
4. В конце выполнения Lexical Enviroment удаляется из памяти компьютера.
5. Для каждого вызова создаётся отдельный объект Lexical Enviroment
Для глобальной функции это свойство равно window
functionName.[[Scope]] = window
Для локальной функции - [[Scope]] равно той функции, внутри которой она создана.
При запуске функции переменная ищется внутри функции, а затем во внешнем окружении, определённом свойством [[Scope]]
Функция получает значение внешней переменной, актуальное на данный момент
Пример
var a = 1;
function num() {
return a;
}
a = 10000;
num(); // 10000
Пример 2а)
var a;
function num() {
return a;
a = 42;
}
num(); // undefined
Пример 2б)
var a;
function num() {
return a;
}
a = 42;
num(); // 42
Инициализация (подготовка к выполнению) внутри него выполняется точно так же, как и в глобальном объекте window.
При вызове функции:
2. Туда помещаются параметры функции и переменные, объявленные внутри неё
3. Функция выполняется. Параметрам и переменным присваиваются значения
4. В конце выполнения Lexical Enviroment удаляется из памяти компьютера.
5. Для каждого вызова создаётся отдельный объект Lexical Enviroment
Свойство [[Scope]]
В момент создания функция получает скрытое свойство [[Scope]], которое содержит ссылку на лексическое окружение, в котором она была создана.Для глобальной функции это свойство равно window
functionName.[[Scope]] = window
Для локальной функции - [[Scope]] равно той функции, внутри которой она создана.
При запуске функции переменная ищется внутри функции, а затем во внешнем окружении, определённом свойством [[Scope]]
Функция получает значение внешней переменной, актуальное на данный момент
Пример
var a = 1;
function num() {
return a;
}
a = 10000;
num(); // 10000
Пример 2а)
var a;
function num() {
return a;
a = 42;
}
num(); // undefined
Пример 2б)
var a;
function num() {
return a;
}
a = 42;
num(); // 42
Вложенная функция
Вложенная функция - это функция, объявленная внутри другой функции.
У вложенной функции несколько внешних объектов переменных.
Вначале она ищет переменную внутри себя, потом во внешнем объекте, потом в ещё более внешнем и т.д
Вложенная функция может быть результатом работы внешней функции
Пример
function makeCounter() {
var currentCount = 1;
return function() {
return currentCount++;
}
}
var counter = makeCounter();
alert (counter()); // 1
alert (counter()); // 2
alert (counter()); // 3
alert (counter()); // 4
var counter2 = makeCounter();
alert (counter2()); // 1
Мы получили два счётчика counter и counter2, каждый из которых определяет количество вызовов функции и сохраняет их в переменной currentCount. Это возможно благодаря тому, что при каждом вызове функции создаётся своё собственное лексическое окружение.
Замыкание - функция вместе с внешними переменными, которые ей доступны.
В JS замыкания в первую очередь это внешний объект переменных. Когда говорят "переменная берётся из замыкания", т.е из внешнего объекта.
Вложенная функция может быть результатом работы внешней функции
Пример
function makeCounter() {
var currentCount = 1;
return function() {
return currentCount++;
}
}
var counter = makeCounter();
alert (counter()); // 1
alert (counter()); // 2
alert (counter()); // 3
alert (counter()); // 4
var counter2 = makeCounter();
alert (counter2()); // 1
Мы получили два счётчика counter и counter2, каждый из которых определяет количество вызовов функции и сохраняет их в переменной currentCount. Это возможно благодаря тому, что при каждом вызове функции создаётся своё собственное лексическое окружение.
Выводы
Замыкание - функция вместе с внешними переменными, которые ей доступны.
В JS замыкания в первую очередь это внешний объект переменных. Когда говорят "переменная берётся из замыкания", т.е из внешнего объекта.
[[Scope]]new Function
new Function всегда глобальная, для неё[[Scope]] = window
Пример
var n = 12;
function a () {
var n = 33;
var c = new Function('', 'return n')
return c;
}
a()() // 12 - берётся глобальная переменная
function a () {
var n = 33;
var c = new Function('', 'return n')
return c;
}
a()() // 12 - берётся глобальная переменная
То есть для new Function не могут использоваться замыкания. Если нужны внешние переменные, их указывают как параметры (здесь не поняла).