Область действия
В вашем коде всего три области действия.Одна из них - это глобальная область видимости всех переменных, которые вы объявляете, а две другие находятся здесь:
var SQUAREPLUSOTHER = x => y => ((x*x) + y + z);
Существует две области действия функции: одна содержит переменную x
, а другая область действия содержит переменную y
,Может быть легче увидеть, если вы замените функцию стрелки на function
s:
// global scope
function SQUAREPLUSOTHER(x) {
// function scope containing x
return function(y) {
// function scope containing y
return (x*x) + y + z;
};
}
Как работает область видимости на самом деле довольно просто:
Every {
запускает новую область видимости, а ее счетчик }
закрывает ее, переменные, объявленные внутри нее с let
и const
(или var
, но это немного сложнее), являются частью области действия.Если это область действия функции, то параметры (например, x
и y
) являются частью этой области.
Из кода вы можете получить доступ ко всем переменным, которыенаходятся в текущей области или в родительской области, если есть несколько с одним и тем же именем, вы получаете наиболее внутреннюю.Поэтому x
внутри функции SQUAREPLUSOTHER
ссылается на переменную области действия SQUAREPLUSOTHER
, в то время как для кода вне ее x
является глобальной переменной, и переменная функций недоступна.
Область действия переменной не изменяется во время выполнения, вы всегда можете непосредственно увидеть, какой области видимости переменной принадлежит tp, взглянув на окружающие {
.. }
.
Теперь разные переменные в разных областях должны содержать значения во время выполнения, вот где мы получаем:
запись среды
Когда вы вызываетеФункция JavaScript создает новый «EnvironmentRecord» (который похож на внутренний объект), который содержит все переменные вызываемой функции, например, в этом случае:
function test(a) {
let b;
}
Затем, если вы вызываете эту функцию(test(1)
) создается новая запись среды, которая содержит a
и b
.Теперь запускается код внутри функции, и в ней ищется каждая переменная.Если есть две функции, вложенные в другую, вызов внутренней функции создаст запись среды, которая содержит ссылку на внешнюю:
function test(a) {
function test2(b) {
}
test2(5);
}
Теперь вызов test(1)
создаст запись, где a
1
.Если механизм затем выполняет второй вызов (test2(5)
), он создает другую запись, содержащую b
, являющуюся 5
, и которая содержит ссылку на запись, содержащую a
.Теперь, если вы используете a
внутри test2
, движок будет искать его в текущей записи среды, не найдет его, а затем ищет в родительском месте, где он найдет a
, являющийся 1
.
closure
Обычно эти записи удаляются, когда выполнение достигает }
, однако, если есть другая запись, получившая текущую запись в качестве родителя, она выигрывает 'удалитьОн будет существовать до тех пор, пока не будут удалены все дочерние записи, тогда он также удалит родительский элемент.Такое поведение (переменные живут дольше, поскольку к ним можно получить доступ из тела внутренних функций) называется закрытием.