我遇到了一个细微的错误,已按如下方式提取:
function huh() {
for (var i = 0; i < 10; i++) {
if ( i % 2 == 1 ) {
var x = i;
console.log(i + ' ' + x);
}
else {
console.log(i + ' ' + x);
}
}
}
huh();
首先,我会挑战即使是经验丰富的JavaScript程序员,也只是在纸上正确预测该程序的确切输出。但主要是,JavaScript似乎混合了动态和词汇范围。似乎没有块范围,只有功能范围,这基本上吹走了我在JavaScript中的整个范围概念。有人可以参考标准解释,也许有点理由吗?这似乎非常反直觉。
答案 0 :(得分:1)
使用let
关键字从ecmascript版本6开始使用JavaScript进行块定义。
除此之外,它与var
语句一起使用的方式是在执行函数之前语句浮动到函数的顶部。变量声明在其他任何内容之前发生,无论它们在哪个块中,包括for循环语句内部。变量的实际赋值确实发生了,所以它们是未定义的,但是在它们被赋值的代码行之前不会被声明。
至于你的具体例子,请记住像数字这样的原始值不是通过引用而是通过值分配的,并且x
的更新只会发生在不均匀的数字上,并且在第一轮时将是未定义的,但是如果它是对象,一旦你将一个对象分配给另一个对象,它们就会引用同一个对象(无论if / else条件如何)。
为了提供进一步的混淆,请注意浏览器中的控制台是异步的,因此您可以将对象打印到控制台(尽管不是基元)并检查它们在{{1}时无法获得对象状态的位置声明,但在以后的时间。这对调试非常困惑。
是的JavaScript在实践中肯定有一点学习曲线。
答案 1 :(得分:1)
这种有点令人费解的效果是功能范围和variable hoisting的组合。
您应该考虑上述代码等同于:
function huh() {
var i, x;
for (i = 0; i < 10; i++) {
if ( i % 2 == 1 ) {
x = i;
console.log(i + ' ' + x);
}
else {
console.log(i + ' ' + x); }
}
}