Сегодня мне пришло в голову другое использование, поэтому я с энтузиазмом искал в Интернете и нашел упоминание об этом: определение переменных внутри блока .
Фон
JavaScript, несмотря на внешнее сходство с C и C ++, не включает переменные в блок, в котором они определены:
var name = "Joe";
if ( true )
{
var name = "Jack";
}
// name now contains "Jack"
Объявление замыкания в цикле является распространенной задачей, где это может привести к ошибкам:
for (var i=0; i<3; ++i)
{
var num = i;
setTimeout(function() { alert(num); }, 10);
}
Поскольку цикл for не вводит новую область видимости, то же самое num
- со значением 2
- будет использоваться всеми тремя функциями.
Новая сфера: let
иwith
С введением let
оператора в ES6 становится легко вводить новую область, когда необходимо избежать этих проблем:
// variables introduced in this statement
// are scoped to each iteration of the loop
for (let i=0; i<3; ++i)
{
setTimeout(function() { alert(i); }, 10);
}
Или даже:
for (var i=0; i<3; ++i)
{
// variables introduced in this statement
// are scoped to the block containing it.
let num = i;
setTimeout(function() { alert(num); }, 10);
}
Пока ES6 не станет универсально доступным, это использование будет ограничено новейшими браузерами и разработчиками, желающими использовать транспортеры. Тем не менее, мы можем легко смоделировать это поведение, используя with
:
for (var i=0; i<3; ++i)
{
// object members introduced in this statement
// are scoped to the block following it.
with ({num: i})
{
setTimeout(function() { alert(num); }, 10);
}
}
Цикл теперь работает так, как задумано, создавая три отдельные переменные со значениями от 0 до 2. Обратите внимание, что переменные, объявленные в блоке, не ограничены им, в отличие от поведения блоков в C ++ (в C переменные должны быть объявлены в начале блок, так что в некотором роде это похоже). Это поведение на самом деле очень похоже на let
блочный синтаксис, представленный в более ранних версиях браузеров Mozilla, но не получил широкого распространения в других местах.