Javascript 为什么变量在它之外可用';s代码块?

Javascript 为什么变量在它之外可用';s代码块?,javascript,Javascript,5分钟前我碰到了这个小宝石。我使用JavaScript已经有很长一段时间了,自从我遵循最佳实践以来,我从未遇到过这种情况,也不理解为什么它可以工作,而我认为它不应该: for (var i=0; i<10; i++){ // ... something } console.log("i=", i); for(var i=0;i,因为这相当于: var i=0; while (i<10){ // ... something i++; } var i=0; 而 我一

5分钟前我碰到了这个小宝石。我使用JavaScript已经有很长一段时间了,自从我遵循最佳实践以来,我从未遇到过这种情况,也不理解为什么它可以工作,而我认为它不应该:

for (var i=0; i<10; i++){
   // ... something
}
console.log("i=", i);

for(var i=0;i,因为这相当于:

var i=0;
while (i<10){
   // ... something
   i++;
}
var i=0;
而
我一直认为声明部分应该有一个局部变量,仅在该块中可用

不,不是用JavaScript

JavaScript循环(通常包括大多数块)没有块作用域(直到下一个版本推出
let

目前只有两个地方JavaScript会阻止作用域,那就是
子句(无论如何都不应该使用这些子句)以及
catch
子句


相反,JavaScript主要依赖于函数作用域-函数中声明的变量是该函数的本地变量。

在这种情况下,
i
的声明在代码块之外。在任何情况下,JavaScript都没有块级别的作用域。变量要么是全局变量,要么在函数的作用域内。

i
将e除非关闭范围,否则可在您定义范围的下方使用,如:

(function(){
  for(var i=0; i<10; i++){
  }
})();
console.log(i); // undefined
或者像这样的循环:

var ar1 = ['a', 'b', 'c']; 
for(var i=0,l=ar1.length,n=0; i<l; i++,n+=2){
}
// feel free to use `i`, `l`, and `n` again
var ar1=['a','b','c'];
对于javascript中的(var i=0,l=ar1.length,n=0;i,没有“块作用域”,只有“函数作用域”。这意味着,一旦在函数中定义了变量,它们将从声明时起一直保持活动状态,直到函数结束,无论是在块内还是在块外

以下是js变量范围的测试用例(来自第3.2.1节范围和函数)

测试用例:

function outer(){
  var a = 1;
  function inner(){ /* does nothing */ }
  var b = 2;
  if (a == 1) {
    var c = 3;
  }
}
outer();
结果:


很有趣。就像我说的,我从来没有写过这样……糟糕的代码,所以如果不尝试的话,我绝对不会猜到。@BenjaminGruenbaum是的,我想是的;那么我就删除规范引用:P@Doorknob这些是你要找的机器人:)@BenjaminGruenbaum仍然没有真正列出什么创建了一个新的范围,什么没有though@Doorknob不,它不是,而且这个列表比人们想象的要详尽得多,它不仅仅是
catch
,FunctionExpression,FunctionDeclaration和global scope(尽管它们是主要的)。如果您在大多数情况下避免使用eval(直接或间接)作用域(更不用说宿主对象扩展)。这就是通常错误但足够好的“JS仅具有函数作用域”的原因:)这个答案或多或少与建议的“重复”问题相同。(很抱歉重复。责怪谷歌在查询关于这个主题的各种事情时不够聪明。)@YanickRochon作为将来的参考,这被称为“提升”变量。请参阅
var
@jasonscript,我第一次看到这个词:)(不是母语英语。)@YanickRochon提升的意思几乎是“提升”。因此,var声明会自动提升到功能块的顶部。很抱歉,这并不能直接解决问题。问题不是找到隔离
I
,而是为什么它在
for
块之外可见。在javascript中,没有“块范围”'这句话是不正确的。在这里,我指的是块作用域{},而不是()。当然,使用(),我们可以创建一个像PHPglue上面所说的自动执行函数。这反过来又会创建一个闭包。你想提一下这种情况吗?
try{throw 5}catch(x){/*x是在这个作用域中定义的,等于5*/}
var ar1 = ['a', 'b', 'c']; 
for(var i=0,l=ar1.length,n=0; i<l; i++,n+=2){
}
// feel free to use `i`, `l`, and `n` again
function outer(){
  var a = 1;
  function inner(){ /* does nothing */ }
  var b = 2;
  if (a == 1) {
    var c = 3;
  }
}
outer();