今天我想到了另一个用途,所以我兴奋地在网上搜索,发现了一个现有的提及:在块作用域内定义变量.
背景
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
and 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);
}
Or even:
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 的独立变量。请注意,声明的变量within与 C++ 中块的行为不同,块的作用域不限于它(在 C 中,变量必须在块的开头声明,因此在某种程度上是相似的)。这种行为实际上非常类似于let块语法在早期版本的 Mozilla 浏览器中引入,但并未在其他地方广泛采用。