0

这是我的代码:

function func(){
 for(i=0; i < 5; i++){
   alert('g');
 }
}

for(i=0; i < 5; i++){
  func();
  alert('h');
}

我所期望的是:

但收到的只是ggggh

我发现这是因为 JS 中存在函数作用域,而不是块作用域。我想知道的是如何保持这种行为。我的意思是强制使用块范围之类的东西。否则很容易产生真正令人讨厌的错误——例如,在使用其他人编写的函数或您自己编写的函数时,但在几个月前。

4

4 回答 4

3

这实际上与函数与块范围无关 - 它与隐式全局变量有关。

简短的故事:您不小心在循环中创建了一个全局变量for- 如果您使用for(var i=0;而不是for(i=0;您将获得预期的结果。

稍长的版本:

alert("typeof i: " + typeof i);
// Alerts "typeof i: undefined"    
function func() {
  // References the *global* variable `i`
  for(i=0; i < 5; i++){
    alert('g');
  }
}

// Creates a *global* variable `i` and sets it to 0
for(i=0; i < 5; i++) {
   alert("i at start of iteration: " + i);
   // Alerts "i at start of iteration: 0"
   func();
   // `func` has just altered *global* state - here's the proof
   alert("i after call to func: " + i);
   // Alerts "i at start of iteration: 5"
   alert('h');
}
alert("typeof i: " + typeof i);
// Alerts "typeof i: number
// `i` is now in the global scope.

// Left as an exercise for the reader:
// try it again with `var i=0;` in both of the `for` loops.
于 2012-11-06T03:30:30.040 回答
2

变量 i 的范围存在问题。

function func(){
 for(var i=0; i < 5; i++){
   alert('g');
 }
}

for(var i=0; i < 5; i++){
  func();
  alert('h');
}
于 2012-11-06T03:31:34.173 回答
0

尝试i在函数中声明为局部变量:

function func(){
   var i;
   for(i=0; i < 5; i++){
     alert('g');
   }
}
于 2012-11-06T03:32:00.993 回答
0

正如其他答案中已经说明的那样,您的代码不起作用,因为您没有使用 声明i变量var,这会自动使其成为全局变量。所以不是真正的功能与块范围问题。如果你var用来声明你的变量,那么变量的范围将被限制在声明包含在任何嵌套函数中的同一个函数中,或者如果不在函数中,则为全局。

如果您在嵌套函数中使用相同的变量名称,则内部范围内的变量称为“遮蔽”外部变量;在这种情况下,内部函数无法访问该名称的外部函数变量,因为使用该名称只会给它自己的变量。可以这么说。尽管您可以通过将全局变量视为window对象的属性来访问它们。

“我想知道的是如何保留这种行为。我的意思是强制使用块作用域之类的东西。否则很容易产生非常讨厌的错误......”

不,一旦您开始var正确使用,避免这些错误并不难。但是你可以通过引入一个立即调用的匿名函数来强制块作用域:

(function() {
    // variables created in this function are accessible
    // only within this function
    var x, y, z;
})();

console.log(typeof x); // "undefined" (x can't be seen from outside the function)

括号function(){}是必需的,以便函数被解释为表达式而不是函数语句;最后的额外()内容是使该函数表达式立即执行。这种结构的一个常见用途是将整个脚本包含在其中,这样其中的变量或函数就不会成为全局变量,因此不会与从其他 JS 包含文件加载的其他脚本交互。(您可以在块内的多个函数之间共享伪全局变量,这些函数也在块内声明。)

因此,例如,如果您想将for语句的主体变成具有范围的“块”,您可以这样做:

for (var i = 0; i < something; i++) {
    (function() {
        var x = i;
        // do something with x
    })();
}
于 2012-11-06T04:01:20.057 回答