ES5
и ранее:
Переменные в Javascript изначально (до ES6
) были ограничены лексической функцией. Термин лексически ограниченный означает, что вы можете увидеть область действия переменных, «посмотрев» на код.
Каждая переменная, объявленная с ключевым словом var
, находится в области видимости функции. Однако, если в этой функции объявлена другая функция, эти функции будут иметь доступ к переменным внешних функций. Это называется цепочкой областей действия . Работает следующим образом:
- Когда функция ищет разрешение переменной, она сначала смотрит на свою область видимости. Это тело функции, т. Е. Все, что заключено в фигурные скобки {} (за исключением переменных внутри других функций , которые находятся в этой области).
- Если он не может найти переменную внутри тела функции, он поднимется до цепочки и рассмотрит область видимости переменной в функции в , где была определена функция . Это то, что подразумевается под лексической областью действия, мы можем видеть в коде, где была определена эта функция, и, таким образом, можем определять цепочку области действия, просто просматривая код.
* +1025 * Пример:
// global scope
var foo = 'global';
var bar = 'global';
var foobar = 'global';
function outerFunc () {
// outerFunc scope
var foo = 'outerFunc';
var foobar = 'outerFunc';
innerFunc();
function innerFunc(){
// innerFunc scope
var foo = 'innerFunc';
console.log(foo);
console.log(bar);
console.log(foobar);
}
}
outerFunc();
Что происходит, когда мы пытаемся зарегистрировать переменные foo
, bar
и foobar
на консоли, следующее:
- Мы пытаемся войти в консоль foo, foo находится внутри самой функции
innerFunc
. Поэтому значение foo преобразуется в строку innerFunc
.
- Мы пытаемся подключить панель к консоли, панель не может быть найдена внутри самой функции
innerFunc
. Поэтому нам нужно подняться по цепочке прицелов Сначала мы посмотрим на внешнюю функцию, в которой была определена функция innerFunc
. Это функция outerFunc
. В области outerFunc
мы можем найти переменную bar, которая содержит строку «externalFunc».
- foobar не может быть найден во innerFunc. , Поэтому нам нужно подняться по цепочке областей действия к области видимости innerFunc. Это также не может быть найдено здесь, мы поднимаемся на другой уровень к глобальной области видимости (т.е. самой внешней области видимости). Здесь мы находим переменную foobar, которая содержит строку «global». Если он не найдет переменную после перехода по цепочке областей видимости, двигатель JS выдаст referenceError .
ES6
(ES 2015) и старше:
Те же самые понятия лексической области действия и области видимости все еще применяются в ES6
. Однако были введены новые способы объявления переменных. Есть следующее:
let
: создает переменную области видимости блока
const
: создает переменную области блока, которая должна быть инициализирована и не может быть переназначена
Наибольшее различие между var
и let
/ const
заключается в том, что var
является функциональной областью, тогда как let
/ const
является блочной областью. Вот пример, чтобы проиллюстрировать это:
let letVar = 'global';
var varVar = 'global';
function foo () {
if (true) {
// this variable declared with let is scoped to the if block, block scoped
let letVar = 5;
// this variable declared with let is scoped to the function block, function scoped
var varVar = 10;
}
console.log(letVar);
console.log(varVar);
}
foo();
В приведенном выше примере letVar записывает глобальное значение, потому что переменные, объявленные с let
, имеют область видимости блока. Они перестают существовать вне соответствующего блока, поэтому к переменной нельзя получить доступ вне блока if.