JavaScript函数循环循环迭代器问题?

时间:2012-11-06 03:27:43

标签: javascript

这是我的代码:

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

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

我的期望是:gggghgggghgggghgggghggggh

但收到的只是ggggh

我发现那是因为JS中存在函数范围,而不是块范围。我想知道的是如何保持这种行为。我的意思是强制阻止范围。否则很容易制造出令人讨厌的错误 - 例如使用其他人写的函数或你自己编写的函数,但几个月前。

4 个答案:

答案 0 :(得分: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.

答案 1 :(得分:2)

变量i的范围问题。

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

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

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

正如其他答案中所述,您的代码无效,因为您没有使用var声明i变量,这会自动使其成为全局变量。所以不是功能与块范围问题。如果使用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
    })();
}