Пусть переменная область
Следующий код выведет "1" Однако, не должно ли ключевое слово "let" не делать глобальную переменную x a, делая ее невидимой для das()? Предполагается, что let ограничивает область видимости переменных только блоком, в котором они объявлены, но здесь я вижу, что внутренняя функция имеет доступ к переменной let, хотя x был объявлен вне ее области. Как это возможно?
function letTest() {
function das () {
console.log(x);
// How does this function have access to a let variable declared outside its scope?
}
let x = 1;
das();
}
letTest();
7 ответов
Вот способ думать о том, как let
работает:
- Начните с
let
, - На том же уровне вложенности, работая обратно / вверх по исходному коду, найдите первый
{
, - Теперь из
let
найти соответствующий}
,
Это дает вам область, в которой переменная будет видимой. Если определение функции появляется в этой области, хорошо; переменная видима для кода в этой функции.
Теперь, что немного странно, так это то, что в вашем примере переменная выглядит так, как будто она использовалась в области видимости до того, как была объявлена. Вот где факт, что ссылка появляется до объявления, становится немного интереснее.
Обычно, если код в области видимости ссылается на let
переменная перед let
на самом деле происходит, это ошибка. Однако, это вещь времени выполнения, а не синтаксис. В вашем случае во время выполнения let
произойдет к тому времени, когда будет вызвана вложенная функция.
let
ограничивает область действия переменной текущим блоком (в этом случае он совпадает с letTest
функция).
das
Функция объявлена внутри этой области, поэтому она имеет доступ ко всему в этой области (включая x
).
Дело в том, что вы не изменяете значение x, в вашем случае вы просто записываете его на консоль, и все они вложены в одну область видимости, которая не ограничивает внутреннюю функцию, поэтому ваш результат ожидается.
Теперь, если вы сделали что-то подобное
function letTest() {
function das () {
console.log(x);
// How does this function have access to a let variable declared outside its scope?
}
let x = 1;
function change(){
x = x + 1;
}
change();
}
letTest();
Теперь вы пытаетесь изменить значение x, и компилятор будет жаловаться.
@GTS Джо,
let x
является локальным для letTest()
поэтому контекст das()
просто доступ к его x
переменная. Ничего странного там не происходит. Итак, "нет" - это не становится глобальным.
Независимо от того, насколько глубоко контекст вызова переменной был вложен, всегда есть принцип поиска JS, который будет следовать при неудачном просмотре и будет продолжать искать это имя переменной в глобальной области видимости, и только тогда - когда ничего не найдено - это вызовет ошибку ссылки.
И это - только потому, что принцип JS не рассматривается ниже - возможны так называемые замыкания.
Как описано здесь: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let обеспечивает доступ в пределах блока. Как твой das()
выполнение и объявление x находятся в той же области видимости блока, к которой у них будет доступ.
Хороший пример приведен ниже, с использованием var x = 'x'
в случае 1 он будет привязан к области действия функции и доступен в console.log(), но при попытке сослаться на переменную bar для регистрации он выдает исключение ссылки. Но все еще работает в случае по умолчанию.
const example = (foo) => {
switch(foo) {
case 0:
break;
case 1:
let bar = 'bar';
var x = 'x';
break;
default:
console.log(bar);
break;
}
console.log(x);
console.log(bar);
}
example(1);
Функция объявлена в том же блоке, что и x
поэтому код внутри функции имеет доступ к x
,
Если вы этого не хотите, вы всегда можете добавить новый блок:
function letTest() {
function das () {
console.log(x); // ReferenceError
}
{ // New block
let x = 1;
das();
}
}
letTest();
Это не выходит за рамки. x и das () определены в одной области блока. Все остальное в этом блоке имеет доступ к x. Сюда входят любые вложенные функции, циклы for, циклы while и условные выражения if. Сюда входят «elseif» и «else», которые находятся внутри условного «if».