Пусть переменная область

Следующий код выведет "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 работает:

  1. Начните с let,
  2. На том же уровне вложенности, работая обратно / вверх по исходному коду, найдите первый {,
  3. Теперь из 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».

Другие вопросы по тегам