Каково фактическое преимущество использования области видимости let/block?

Кажется, я не вижу фактического преимущества использования let. Конечно, если бы у меня был цикл for, я бы использовал let i = 0 вместо var i = 0, а i теперь относился бы к области действия блока цикла for. Но так ли это выгодно? Я имею в виду, что я могу использовать var и иметь доступ к области действия переменной, но просто не использовать ее там, где мне это не нужно? В чем преимущество блокировки области видимости?

Я понимаю разницу между var и let, мне нужно более последовательное понимание конкретных преимуществ let.


person Community    schedule 03.11.2016    source источник
comment
Возможный дубликат let ключевое слово против ключевого слова var в Javascript   -  person Alexander O'Mara    schedule 03.11.2016


Ответы (1)


Вы уже упомянули одно преимущество: блочная область в циклах. Это позволяет избежать проблем с определением функций внутри цикла, что, по моему мнению, является одной из самых больших ловушек для новичков в JavaScript. :

// With var
var elements = document.querySelectorAll('.var');
for (var i = 0; i < elements.length; i++) {
  elements[i].onclick = function() {
    console.log("I'm element #" + (i + 1) + ".");
  };
}

// With let
elements = document.querySelectorAll('.let');
for (let i = 0; i < elements.length; i++) {
  elements[i].onclick = function() {
    console.log("I'm element #" + (i + 1) + ".");
  };
}
<h3>With <code>var</code></h3>
<div class="var">Click me!</div>
<div class="var">Click me!</div>

<h3>With <code>let</code></h3>
<div class="let">Click me!</div>
<div class="let">Click me!</div>

Еще одним преимуществом является то, что переменные let не инициализируются по умолчанию. Это упрощает обнаружение ошибок при попытке доступа к переменной с тем же именем в более высокой области видимости:

// With `var`, we get `undefined` which can be tricky to debug in more
// complex code.
var foo = 42;

function bar() {
  console.log(foo); // undefined
  var foo = 21;
}
bar();

// With `let`, we get a ReferenceError, which makes it clear that we made
// a mistake here.
var foo = 42;

function bar() {
  console.log(foo); // ReferenceError
  let foo = 21;
}
bar();


В целом это больше согласовывает JavaScript с тем, как работают другие языки.

person Felix Kling    schedule 03.11.2016
comment
Просто чтобы убедиться, что я понял это. Итак, в первом примере foo не равно 42, как только вызывается bar(), он становится неопределенным, потому что он снова был объявлен с var внутри функции, верно? - person ; 03.11.2016
comment
Спасибо, почитаю еще о преимуществах определения функций внутри цикла. Так правильно ли будет сказать, что переменные, объявленные с помощью let, не поднимаются? - person ; 03.11.2016
comment
(Я добавил пример, касающийся функций...) Вокруг этого было довольно много дискуссий, потому что разные люди связывают с подъемом разное значение. Но ответ положительный: подъем означает, что переменная объявляется и инициализируется значением по умолчанию (undefined). Объявления let объявляются, но не инициализируются по умолчанию. Однако они по-прежнему скрывают внешние переменные с тем же именем. - person Felix Kling; 03.11.2016
comment
Вау, большое спасибо за фрагмент кода. Полностью увидеть применение области видимости блока сейчас. - person ; 03.11.2016