我知道<reference name="left">
<block type="catalog/navigation" name="catalog.leftnav" after="currency" template="catalog/navigation/left.phtml"/>
</reference>
是声明块范围局部变量,但为什么它不支持重新声明和像let
那样的提升?
此限制的设计目的是什么?
var
答案 0 :(得分:8)
我们的想法是创建一个比原始var
更明确,更严格的工具。
作为一个人,以下是有效的JavaScript,但几乎无法理解:
alert(a); // Where does a come from? Why does this not throw?
/* 1000 lines later, or even in an entirely different file */
var a;
此外,想象代码在同一范围内对同一变量有5 var
个声明,有些在if
语句中,有些在for
s中。哪个是第一个?最终会创造什么价值?
我们的想法是修复一些 bad parts of var
。
答案 1 :(得分:1)
任何编程语言中出现任何严格操作符的原因相同 - 限制你可以用脚射击自己的方式。老派的Javascript只是充满了那些。
请注意,您可以将let
用于块本地范围:
while (i < 5)
{
let a = 42;
i++;
}
即使循环运行了几次,a
也始终正确初始化。
现在,如果你在更高的范围内有另一个变量,会发生什么?
let a = 42;
while (i < 5)
{
let a = 10;
// What is the value of a here?
i++;
}
// And here?
这里存在一定程度的模糊性 - 模糊性是编程语言中的一个不好的特征。这不是非块范围var
的问题 - 一个人有很多自己的问题,人们总是滥用它,但至少明显var
是永远块范围。即便如此 - 人们也会像使用 块范围一样使用它。
解决这种疯狂的唯一方法是使语言更加严格。这真的意味着你失去了任何功能吗?不可变。使用var
变量阴影是一个坏主意,let
仍然是一个坏主意(正如我的例子所示,可能更糟)。
这不是Javascript独有的,不是长篇大论。例如,在C#中:
int i = 0;
int i = 42; // Compiler error: A local variable named 'i' is already defined in this scope
为什么呢?因为你显然犯了错误。也许您从其他地方复制了一段代码,并没有注意到您已经声明了另一个名为i
的变量。也许你忘记了你正处于另一个循环的中间,它也使用i
作为循环变量。没有真正的合法用途,但是有大量的失败模式 - 这只是一种糟糕的语言特征。简单的编译器错误可以防止几乎所有这些失败发生 - 并且很多失败很难找到,特别是如果不经常使用“内部”块。